Nobody has started this yet — be first.
Business impact
GET /healthz exists so an orchestrator -- Kubernetes, a load balancer, an uptime monitor -- can tell whether this instance can actually do its job. Every feature this service offers goes through Redis, so if /healthz reports "ok" while Redis is completely unreachable, nothing routes traffic away from a fully broken instance -- every stream and publish call it receives will fail while its health check keeps insisting everything is fine. This is exactly the failure mode a health check exists to catch, inverted into false reassurance, and it stays invisible until the one day Redis actually goes down.
Problem
healthz's except branch, which only runs when redis.ping() has just raised (i.e. Redis is not reachable), sets redis_ok = True -- the exact opposite of what just happened.
Current behavior
With a Redis client whose ping() always raises, GET /healthz still returns 200 {"status": "ok", "redis": true} instead of reporting degraded.
Expected behavior
When redis.ping() raises, redis_ok must be False, and the endpoint should respond with {"status": "degraded", "redis": false}, matching the shape health.py already uses in the success case.
Steps to reproduce
See practice_tickets/tests/test_ticket_03_healthz_lies.py for a runnable repro: build an app whose Redis client's ping() always raises, then hit /healthz -- it currently still returns 200 {"status": "ok", "redis": true}.
Why this matters
This reads as an obvious copy-paste mistake once you see it -- the except branch is a literal duplicate of the try branch's assignment -- but it's exactly the kind of one-character-away typo that's easy to miss in review, because both branches look like reasonable code in isolation. The bug is invisible on the happy path (Redis working, true 99.9% of the time in dev/CI) and only manifests during the one scenario -- an actual Redis outage -- that a health check is supposed to exist for.
Suggested approach
Look at the two branches of the try/except in app/routers/health.py::healthz. One of them is supposed to represent "Redis just failed to respond." Check what value it currently assigns.
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_03_healthz_lies.py -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b fix/healthz-lies-when-redis-downFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/healthz-lies-when-redis-downSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://localhost:8000http://localhost:8001Authorization: Bearer <user_id>X-User-Id: <user_id>curl localhost:8000/healthz
curl -N -H "Authorization: Bearer alice" localhost:8000/notifications/stream
# watch `: heartbeat` lines arrive roughly every 15s with no other traffic
Work the tickets in practice_tickets/tickets/ (ordered easy → hard); each names one dedicated pytest test in practice_tickets/tests/:
pytest practice_tickets/tests/test_ticket_01_heartbeat_default_margin.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 15, clean pass/fail summary
Tickets 14 and 15 need genuinely concurrent, long-lived streams, which the ASGI test transport used everywhere else in this project can't represent -- their tests spin up a real (short-lived) uvicorn server on a loopback socket instead (LiveServer in practice_tickets/tests/conftest.py).
Level 1
Fix a bug
Read existing behaviour, correct it.