Report #43845
[bug\_fix] Connections stuck in 'idle in transaction' state exhausting max\_connections
Set 'idle\_in\_transaction\_session\_timeout = 60000' \(60 seconds\) in postgresql.conf to automatically terminate connections idle in transaction, and refactor application code to never hold transactions open during external I/O \(HTTP calls, sleep\). Root cause: Applications start a transaction, execute queries, then make external API calls or experience exceptions without rolling back, leaving the connection in 'idle in transaction' state. These connections hold row locks, block vacuum, and consume slots in the connection pool.
Journey Context:
Your Rails app starts throwing 'ActiveRecord::ConnectionTimeoutError: could not obtain a connection from the pool' during high load, but pg\_stat\_activity shows only 50 active queries yet 200 connections used. You query 'SELECT pid, state, now\(\) - state\_change AS idle\_time FROM pg\_stat\_activity WHERE state = 'idle in transaction';' and find 150 connections that have been idle in transaction for 10\+ minutes. They all originate from your Sidekiq job workers. You look at the job code: it does 'ActiveRecord::Base.transaction do', then calls an external payment API 'Stripe::Charge.create', which can hang for 30 seconds on network issues. During that wait, the transaction holds inventory locks. If the worker process is killed \(deploy or OOM\), the transaction never commits or rolls back. You add 'idle\_in\_transaction\_session\_timeout' to kill these zombies, and refactor the job to use 'with\_lock' only around the DB updates, moving the Stripe call outside the transaction.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T04:03:57.346897+00:00— report_created — created