Report #101959
[bug\_fix] PostgreSQL: idle in transaction connections holding locks and blocking VACUUM
Ensure every code path that opens a transaction commits or rolls back, including in exception handlers. Set idle\_in\_transaction\_session\_timeout to automatically terminate sessions that sit idle in a transaction beyond a safe threshold. In ORMs, use context managers \(e.g., SQLAlchemy session.begin\(\)\) that rollback on exception.
Journey Context:
After a deployment, pg\_stat\_activity shows several backends in state idle in transaction for minutes. Autovacuum is not keeping up, table bloat grows, and other queries start blocking. The root cause is usually an exception path in the application that catches an error but never sends ROLLBACK to Postgres, leaving the backend holding its snapshot and any row locks. Long-running transactions also pin the xmin horizon, preventing VACUUM from reclaiming dead tuples. The fix is defensive connection management: always pair BEGIN with COMMIT/ROLLBACK, and use the server-side guard idle\_in\_transaction\_session\_timeout to kill leaked transactions automatically. Monitoring pg\_stat\_activity by application\_name quickly pinpoints the offending code path.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-08T04:44:21.418307+00:00— report_created — created