No alerting on prod 5xx: 87 errors in 24h (incl. 5x /healthz, 5x homepage) went entirely undetected #54
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Jinemi/thermograph#54
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Prod served 87 HTTP 5xx in the last 24h against 11,079 requests (0.79% error rate). None of it triggered any alert. It was found only by manually querying Caddy access logs in Loki. Five of the failures were
/healthzitself - the endpoint whose entire job is to be noticed when it fails - and five were the homepage.Evidence (re-derived 2026-07-24 ~19:45 UTC, prod Caddy logs via Loki)
Total requests, 24h:
5xx by status:
By route (
sum by (request_uri, status) (count_over_time(... [24h]))):Composition - three distinct causes, only one of them new
1. 69x 503 - the
thermograph-lbreboot race. 67 of the 69 fall inside a single one-hour bucket:This is already root-caused in the note
notes/2026-07-24-ci-runner-had-no-persistent-systemd-unit-fixed-rca-for-the-j.md(finding #2):thermograph-lbis a plain container, not a Swarm service, so its startup is not ordered against or health-gated on the Swarm services it proxies to. On reboot there is a window where everythermograph_*service reports1/1while the LB is not yet serving. That note explicitly left it "flagged for the operator to decide priority on; not acted on unilaterally." This issue is the tracking item for that deferred decision.2. 16x 502 on
/api/v2/geocode- all of these are the_REVGEO_LOCKNameError, which was fixed during this investigation (PR #51; prod and beta both serve 200 now). Not a separate defect - listed only so the 87 reconciles.3. 2x 500 - content-route timeouts. Both served to Googlebot, both ~10s wall time, 35-byte JSON error body from uvicorn:
The ~10s duration points at an upstream timeout on the content path rather than a logic error. PRs #47 / #48 / #49 (content cache token, derived-store-first, off-request pre-warm) all target this path and may already have addressed it - worth confirming these stop recurring rather than fixing twice.
Impact
Real users, and Googlebot, hit 5xx and nobody found out. The 503 window took the homepage down. The
/healthz503s mean an external health check would have caught it - if one existed. Today the only detection mechanism is a human deciding to run a LogQL query, which is how this was found.Suggested action
/healthznon-200. Grafana dashboards/alerts are provisioned from repo JSON, so this goes in as a PR - UI edits get overwritten on the next provision.thermograph-lbstartup-ordering question the RCA note deferred (health-gate the LB, or accept the gap as bounded and document it as accepted).Filed from a verified reproduction; all figures above re-derived from logs at filing time rather than carried over from an earlier report.