Postgres Idle-in-Transaction Session Remediation Prompt
Track down long 'idle in transaction' sessions that hold locks and pin the xmin horizon so autovacuum can't reclaim dead tuples, then decide what to terminate, what to fix in the app, and which timeouts to set — before bloat and lock waits cascade into an outage.
- Target user
- DBAs and SREs debugging lock waits, bloat, and stuck vacuum on production Postgres
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior PostgreSQL DBA. You understand that a session sitting in "idle in transaction" is not harmless idle time: it still holds any locks it acquired, and its open snapshot pins the cluster-wide xmin horizon so autovacuum cannot remove dead tuples newer than that transaction — quietly causing bloat, blocked queries, and in the worst case wraparound risk. Your job is to identify the offenders, weigh termination against app-side fixes, and set the timeouts that prevent recurrence. I will paste: - pg_stat_activity rows filtered to state = 'idle in transaction' (or 'idle in transaction (aborted)'), including pid, usename, application_name, state, wait_event, xact_start, state_change, backend_xmin, and query: [ACTIVITY] - Current lock waits: a pg_locks join or the blocked/blocking pids you have: [LOCKS] - Vacuum / bloat symptoms: pg_stat_user_tables dead tuples or age(datfrozenxid), and the oldest backend_xmin you can see: [VACUUM / XMIN] - Current settings: idle_in_transaction_session_timeout, statement_timeout, lock_timeout, and how the app connects (pooler? ORM? long-lived connections?): [SETTINGS / APP] Work through: 1. **Rank the offenders** — compute how long each idle-in-transaction session has been open (now() - xact_start) and how stale its last activity is (now() - state_change). Flag the session holding the oldest backend_xmin: that one is pinning the vacuum horizon for the whole cluster and is the top priority regardless of the locks it holds. 2. **Map the blast radius** — for each offender, list the locks it holds and which sessions are waiting behind it, and note whether its open snapshot is what is blocking autovacuum on the bloated tables. Separate "blocking other queries" from "blocking cleanup" — both matter, for different reasons. 3. **Decide the action per session** — recommend pg_cancel_backend(pid) to cancel a running statement first, and pg_terminate_backend(pid) only to kill a truly stuck idle transaction; explain that terminating rolls back its open transaction. Prioritize the xmin-pinning session. Call out anything that looks like an app bug (a transaction left open across a network round-trip or user think-time). 4. **Prevent recurrence** — propose idle_in_transaction_session_timeout (globally or per role for the offending app user), and the app-side fix (don't hold a transaction open across external calls; use autocommit or shorter transactions; check pooler settings). Give exact SET / ALTER ROLE / ALTER SYSTEM statements. Output format: (a) offender table [pid | user/app | idle for | oldest xmin? | locks held | waiters], (b) ordered actions with the exact pg_terminate_backend / pg_cancel_backend calls, (c) the timeout and app-side prevention settings, (d) a re-check query on pg_stat_activity and backend_xmin. Guardrails: pg_terminate_backend rolls back the target's open transaction — confirm you are killing the right pid and that a rollback is acceptable before running it. Do not set an aggressive global idle_in_transaction_session_timeout without checking that legitimate long-running batch jobs won't be killed; scope it per role where possible.
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
“Idle in transaction” is one of the most misread states in Postgres. It looks like a connection doing nothing, but the transaction is still open: it holds every lock it took and, more insidiously, its snapshot pins the cluster’s xmin horizon so autovacuum cannot reclaim any dead tuple newer than that transaction. The result is creeping bloat and blocked queries whose root cause is a session that appears idle. This prompt makes that invisible cost explicit by keying the diagnosis on backend_xmin and xact_start, not just on visible lock waits.
It also separates two failure modes engineers routinely conflate: a session blocking other queries versus a session blocking cleanup. Both come from the same idle transaction, but they demand different reasoning — one shows up as lock waits, the other as vacuum falling behind — so the prompt asks for both and singles out the oldest-xmin session as the top priority even when it holds no contended locks.
By forcing a per-session decision between pg_cancel_backend and pg_terminate_backend, and pairing every kill with a prevention step (idle_in_transaction_session_timeout plus the app-side pattern that left the transaction open), the output becomes a safe runbook rather than a blunt “kill the connections.” The guardrails keep termination deliberate and stop an over-aggressive timeout from taking out legitimate batch jobs.
Related prompts
-
Postgres Materialized View Refresh Strategy Prompt
Design a safe refresh strategy for Postgres materialized views — choosing between plain and CONCURRENTLY refresh, scheduling cadence, staleness tolerance, and the unique index CONCURRENTLY requires — so dashboards stay fast without long ACCESS EXCLUSIVE locks or runaway bloat on the matview.
-
Postgres Lock Contention & Deadlock Investigation Prompt
Untangle blocking chains and deadlocks from pg_locks, pg_stat_activity, and log output — pinpoint the blocker, explain the lock conflict, and fix the access pattern so it stops recurring.
-
Postgres VACUUM, Bloat & Autovacuum Tuning Prompt
Diagnose table and index bloat, decide between VACUUM, autovacuum tuning, and a rebuild, and produce per-table autovacuum settings — so dead tuples and wraparound risk stop quietly degrading your database.
-
Postgres Zero-Downtime Schema Migration Planner Prompt
Turn a risky schema change into a lock-aware, multi-step migration plan that avoids long ACCESS EXCLUSIVE locks — with the exact statements, lock_timeout guards, and a back-out path for each phase.
More Postgres prompts & error guides
Browse every Postgres prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.