Report #85074
[bug\_fix] Postgres connection leak: "idle in transaction" causing pool exhaustion
Set \`idle\_in\_transaction\_session\_timeout = 10min\` in postgresql.conf, and fix application exception handling to ensure \`ROLLBACK\` is called in \`finally\` blocks. Root cause: Application code starts a transaction, encounters an exception, catches it without rolling back, and returns the connection to the pool. Postgres keeps the transaction open \(idle in transaction\), holding locks and preventing vacuum, eventually exhausting the connection pool.
Journey Context:
A Python Django app with a custom management command slowly stops responding after 6 hours. Monitoring shows 100% of Postgres connections in state \`idle in transaction\`, all from the app server. The \`pg\_stat\_activity.query\` field shows the last executed SQL was a \`SELECT FOR UPDATE\` from hours ago. Restarting the app fixes it temporarily. Code review reveals a try-except block in a background job: it tries to update inventory, catches \`InventoryError\`, logs it, but never calls \`rollback\(\)\`. The connection is returned to Django's persistent connection pool. Postgres keeps the transaction snapshot open, preventing tuple cleanup \(causing bloat\) and consuming a connection slot. The fix works because \`idle\_in\_transaction\_session\_timeout\` acts as a circuit breaker: if a backend sits idle in a transaction for 10 minutes, Postgres forcibly terminates the connection, rolling back the transaction and releasing the slot. This prevents the pool exhaustion, while fixing the code ensures data consistency without relying on the timeout.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T01:22:55.717723+00:00— report_created — created