Symptom triage
Production doesn't page you about "isolation anomalies" — it pages you about latency, weird numbers, and full connection pools. This chapter is the site in runbook order: start from the symptom, run one query, land on the mechanism you already learned.
| Symptom | Usual suspect | Start here |
|---|---|---|
| Queries hang; latency spikes in bursts | A lock queue behind one long holder — often an idle transaction or unguarded DDL | Who is blocking whom, Table locks & DDL |
| Numbers don't add up; no errors logged | A lost update or write skew — the silent ones | Grep the code for read-modify-write; fix with these patterns |
| Connections pile up until the pool is empty | Sessions stuck idle in transaction | Long & idle transactions, ORM pitfalls |
| Table keeps growing though rows are deleted | Dead tuples; VACUUM starved by a long transaction | Bloat & vacuum health |
Sporadic 40001 / 40P01 errors under load | Serialization failures and deadlocks — expected, must be retried | Logs & counters, the retry wrapper |
| Locks held but no session owns them | An orphaned prepared transaction | SELECT gid FROM pg_prepared_xacts; |
Two habits make every row of this table easier. Name your sessions: every scenario on this site sets application_name, and every triage query returns it, so one line in your connection setup buys you readable pg_stat_activity forever. And alert before the page, because most of these symptoms have a leading indicator, and the alerting checklist lists the handful worth watching.