Runbook: Database connection lost
Symptom: API returns HTTP 500 on all endpoints.GET /ready returns {"status":"error","database":"error","redis":"ok"}. The UI shows a generic error screen.
Diagnose
1. Check the ready endpoint:dial tcp: connection refused— PostgreSQL is not running or not reachable on the configured host/portpassword authentication failed— wrong credentials inDATABASE_URLtoo many connections— connection pool exhausted; PostgreSQLmax_connectionsreachedSSL connection required— PostgreSQL requires TLS butDATABASE_URLhassslmode=disable
DB_MAX_OPEN_CONNS (default: 25) and PostgreSQL’s max_connections (default: 100).
Mitigate
PostgreSQL is down — restart it:pg_isready.
Wrong credentials:
- Update
DATABASE_URLin.envor the Kubernetes secret - Restart the app
DB_MAX_OPEN_CONNS or PostgreSQL’s max_connections, or add connection pooling (PgBouncer).
SSL mismatch:
- If PostgreSQL requires SSL: remove
sslmode=disablefromDATABASE_URLor setsslmode=require - If PostgreSQL doesn’t have SSL: add
?sslmode=disabletoDATABASE_URL
Resolve
- Confirm
GET /readyreturns"database":"ok" - Spot-check the UI — incidents list should load
- Check logs for any delayed background job errors (background workers retry on reconnect automatically)
Prevention
- Run PostgreSQL with a persistent volume — data survives container restarts
- Set
DB_MAX_OPEN_CONNSto no more than 20% of PostgreSQL’smax_connections - Monitor
pg_stat_activityconnection count via Prometheus +postgres_exporter - Configure
/readyas the health check endpoint (not/health) — it verifies the database connection on every call
