Report #66643
[bug\_fix] Long-running 'idle in transaction' connections in PostgreSQL hold locks and prevent vacuum, causing table bloat and performance degradation
Set 'idle\_in\_transaction\_session\_timeout' in postgresql.conf \(e.g., to '5min'\) to automatically terminate connections that remain idle in transaction beyond the threshold. Additionally, audit application code to ensure transactions are committed or rolled back promptly, especially in exception handlers and background job processors.
Journey Context:
A Django developer notices that the 'users' table \(200MB\) has grown to 50GB despite only 10,000 users. Queries are slowing down significantly. Checking 'pg\_stat\_activity', they see several connections in 'idle in transaction' state for 3\+ hours, all originating from a custom management command that processes a large CSV. Investigating 'pg\_locks', they find these idle transactions are holding back the xmin horizon, preventing autovacuum from cleaning dead tuples, leading to massive table and index bloat. The developer manually terminates the backends with 'pg\_terminate\_backend\(\)', but new ones appear when the cron job restarts. They research and find the 'idle\_in\_transaction\_session\_timeout' configuration parameter introduced in PostgreSQL 9.6. They set 'idle\_in\_transaction\_session\_timeout = '5min'' in postgresql.conf and reload. Now idle transactions are automatically killed after 5 minutes, allowing vacuum to proceed and preventing bloat. They also fix the Django management command to use 'transaction.atomic\(\)' context managers with proper exception handling to ensure rollback on errors.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T18:20:33.607020+00:00— report_created — created