DataPilot
Knowledge Base
postgresqloperationsrunbook· Updated 2026-05-30

Runbook: idle in transaction

Why it matters: an open transaction — even idle — pins the xmin horizon: vacuum can't clean dead tuples (bloat grows), and it may hold locks that block DDL/queries.

Find them

sql
SELECT pid, usename, application_name, state,
       now() - xact_start AS xact_age,
       now() - state_change AS idle_for,
       left(query, 80) AS last_query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;

Immediate action

Terminate offenders older than your tolerance (coordinate first if it's a known batch job):

sql
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction'
  AND now() - state_change > interval '15 minutes';

Prevent

  • idle_in_transaction_session_timeout = '10min' (server or per-role) — the single best guardrail.
  • Root causes are almost always application-side: ORMs opening transactions eagerly, missing commit on error paths, humans in psql. Fix the client; the timeout is the seatbelt.
  • Alert on max(now() - xact_start) > threshold, not just session counts.