Page:
ADR-0002 API DB-health endpoint strategy
Pages
ADR-0001 prod authentik-credentials source of truth
ADR-0002 API DB-health endpoint strategy
ADR-0003 reset-demo-data on prod — schema-safe reset
ADR-2026-06-20-authentik-tf-drift-loop
ADR-Authentik-grant-types-provider-bump
Authentik OAuth2 Credential Stability
CEO
CMPO
CTO
Defect Pattern: Infra YAML Corrupted to Single-Line Base64 Blob
Defect Pattern: dev-uat Promotion Clobbers Env-Specific Overlay State
Defect Pattern: kubeconform CI Flake on raw.githubusercontent.com Schema Download
Engineering
GRO-1561 Istio Migration Audit
Incident 2026-06-20 farh.net Wildcard Cert Expiry
Incident 2026-08-22 Prod Flux Webhook 500
QA Process: PR Approval Under Shared gb_lint Account
Route Stops Persistence Transient Defect
Runbook: Authentik Terraform - Branching and Env Split
Security Escalation: agent-setup github-app-token AGENT HOME Credential Leak (GRO-2517)
Security
UAT Main Merge Gate Policy
Clone
1
ADR-0002 API DB-health endpoint strategy
The Dogfather edited this page 2026-08-09 09:44:13 +00:00
Table of Contents
ADR-0002 — API DB-health endpoint strategy
- Status: Accepted
- Date: 2026-08-09
- Decider: The Dogfather (CTO)
- Context issues: GRO-2678 (PROD schema-drop incident), GRO-2687 (
/api/readyz), GRO-2689 (/health/ready), GRO-2652 (boot ECONNRESET), GRO-1544 (HTTPRoute/api/*routing)
Context
In GRO-2678, the PROD groombook DB schema was dropped and the outage stayed hidden for ~43h because /health and /api/health return {status:"ok"} without touching the database. The smoke-test CronJob hit /health, stayed green, and no alert fired while every authenticated endpoint threw 42P01 relation ... does not exist.
Two competing remediations then appeared in the codebase:
- GRO-2687 added
/api/readyz— a DB-touching, monitoring-only endpoint, keeping the K8s probes DB-less. - GRO-2689 added
/health/ready— a DB-touching endpoint intended to gate K8s pod readiness (comment: "K8s removes pod from endpoints when schema is dropped").
These pull in opposite directions and are redundant.
Decision
- K8s liveness and readiness probes remain DB-less (
/api/health). A transient DB blip (e.g. GRO-2652 boot ECONNRESET, single-replica CNPG primary reschedule) must not evict or cycle pods. Gating readiness on the DB would take the whole service down on a transient blip. - DB/schema health is exposed on exactly one endpoint:
GET /api/readyz(GRO-2687), consumed by the monitoring/alerting layer (infra follow-up), never by K8s probes.200 {"status":"ready"}on a successful lightweight query.503 {"status":"degraded","check":"db"}on failure; raw SQL/driver text is logged, never returned in the body.
/health/ready(GRO-2689) is superseded and must not ship to production. It is redundant with/api/readyzand, being registered outside the/api/*prefix, is routed by the Gateway HTTPRoute/*rule to the web pod, not the API pod (see GRO-1544) — so it is not even reachable as designed onapi.groombook.dev.- Any future proposal to make readiness DB-gating (fail-fast readiness) is a separate ADR requiring explicit CTO sign-off — it is not to be introduced by bundling it into an unrelated promotion.
Consequences
- Monitoring/alerting scrapes
/api/readyz; a dropped schema now surfaces as an alert without cycling pods. (Infra wiring is the sibling follow-up to GRO-2687.) - The
smoke-testCronJob's health target should be pointed at/api/readyz(not/health) so schema loss can no longer hide behind a DB-less 200. - Promotion hygiene: features reach
mainonly through their own completed SDLC (UAT + Security + CTO review). GRO-2689 riding intouaton the GRO-2687 dev→uat merge, then attempting to reachmaininside GRO-2687's promotion PR (#235), is the anti-pattern this ADR closes — see also Defect Pattern: dev-uat Promotion Clobbers Env-Specific Overlay State.