idle_session_timeout

idle_session_timeout sets the maximum time a session may sit idle — waiting for the next client query — WHEN NOT inside a transaction.

MEDIUM RISK
Safe first move

If used, set it well above the pool keepalive, per role.

Tier 1 — Lab-Proven — Measured behavior and safety boundaries are available below.

Measured Effect

summary

MEASURED the idle cap terminating a session and a shorter idle surviving. A session connected, set idle_session_timeout, ran one query, then sat idle (state idle, NOT in a transaction); a monitor read pg_stat_activity to check whether the backend survived the idle period.

observations

idle session timeoutidle foroutcomenote
3s~6s (not in txn)TERMINATED (FATAL idle-session timeout)smoking gun: backend gone after idling past the cap
5s~2s (not in txn)SURVIVEDidle under the cap -> connection kept

session survives

It does NOT survive once the cap is exceeded — like idle_in_transaction_session_timeout (#25) it is FATAL: the backend is terminated and the connection closed. The server log shows FATAL: terminating connection due to idle-session timeout. This is the opposite of statement_timeout (#26)/lock_timeout (#27), which cancel a statement non-fatally and keep the session.

reading

It is a hard idle reaper, not a performance dial. A session idle (between transactions) past the limit is killed; the client only learns of it on its next query (server closed the connection unexpectedly). It is purely about reclaiming connection slots/resources held by abandoned idle connections — it has no effect on running statements, on locks, or on the xmin horizon.

honesty note

idle_session_timeout is a server-side timer; the chosen seconds are lab values, the mechanism (terminate-on-idle-exceeded, FATAL, connection closed, ONLY when not in a transaction) is deterministic and box-independent. Survival is observed via pg_stat_activity rather than wall-clock so there is no exec-overhead caveat here.

Reproduced Danger

Sizing / Safe Range

Workload Guidance

Unlock Incident Pro

The free sections tell you what to do. Pro is the measured proof — the exact failure signature, safe-ceiling formula, and per-workload defaults, each captured on real PG 14–18 runs.

  • Reproduced Danger
  • Sizing / Safe Range
  • Workload Guidance
Unlock Incident Pro

idle_session_timeout sets the maximum time a session may sit idle — waiting for the next client query — WHEN NOT inside a transaction. If a connection stays idle (state idle) longer than the limit, the backend is terminated with a FATAL error — FATAL: terminating connection due to idle-session timeout — closing the connection; the client only discovers it on its next query. The default is 0, meaning sessions may stay idle forever. Two scope facts are essential: (1) it counts ONLY idle time between transactions, not idle time INSIDE an open transaction — that is idle_in_transaction_session_timeout's job; and (2) it is FATAL (session terminated), like idle_in_transaction_session_timeout and unlike the non-fatal statement_timeout/lock_timeout. Its purpose is operational hygiene: reclaim connection slots and server resources held by abandoned or forgotten idle connections, rather than data-correctness or bloat control. Because context=user it can be set per session, role, database, or cluster-wide and takes effect immediately. It exists on PG 14-18 (no version cliff).

name

idle_session_timeout

setting default

0 (disabled — idle forever)

unit

ms

vartype

integer

category

Client Connection Defaults / Statement Behavior

context

user

min val

0

max val

2147483647

enumvals

(n/a — integer ms)

boot val

0

reset val

0

pending restart

false

short desc

Sets the maximum allowed idle time between queries, when not in a transaction.

ground truth note

Captured literally from pg_settings on PG 14-18 (-18) on 2026-06-20. setting=0, boot_val=0, reset_val=0 on EVERY version (default_changed=false) — the guard ships DISABLED. context=user (session-changeable, no reload/restart). vartype=integer, unit=ms, min_val=0 (0 disables), max_val=2147483647. category='Client Connection Defaults / Statement Behavior', short_desc='Sets the maximum allowed idle time between queries, when not in a transaction.' Identical across 14, 15, 16, 17, 18.

Common Pitfalls

  • Assuming idle_session_timeout guards against idle-in-transaction bloat — it does NOT; it ignores in-transaction idle. Use idle_in_transaction_session_timeout for that.
  • Setting it below a connection pool's idle interval — the server reaps pooled idle connections, and the app then borrows dead connections (intermittent 'server closed the connection').
  • Forgetting it is FATAL (session terminated), not a per-statement cancel — clients are disconnected and must reconnect.
  • Using it on heavily-pooled application roles where the pool already recycles idle connections — usually redundant and risky there.
  • Setting one aggressive global value instead of per-role — interactive roles want reaping, pooled app roles do not.
  • Expecting it to bound running statements or whole transactions — it only counts BETWEEN-transaction idle time.

Evidence and References

  • PostgreSQL docs: Runtime Config — Client Connection Defaults / Statement Behavior (idle_session_timeout — terminate any session idle longer than the limit; note it does NOT apply when within an open transaction; 0 disables).
  • PostgreSQL docs: idle_in_transaction_session_timeout (the sibling that DOES bound idle time inside a transaction — the snapshot-pinning/bloat case idle_session_timeout ignores).
  • PostgreSQL docs: pg_stat_activity — the state column (idle vs idle in transaction) that distinguishes which of the two idle timeouts applies.
  • PostgreSQL docs: statement_timeout, lock_timeout, transaction_timeout (the rest of the timeout family — run time, lock wait, and total transaction respectively; transaction_timeout new in PG 17).
  • Lab capture 2026-06-20: — a session idle ~6s (not in a txn) under idle_session_timeout=3s was terminated (FATAL idle-session timeout) while idle ~2s under 5s survived ; a tight cap reaped an idle pooled connection, and an idle-in-transaction session survived idle_session_timeout=2s but was terminated by idle_in_transaction_session_timeout=2s ; boundary min=0 disables, range error on -1, context=user, identical /; pg_settings ground truth PG 14-18 (-18).

Technical Reference

Category
Client Connection Defaults / Statement Behavior
Type
integer (ms (milliseconds; 0 disables))
Blast radius
session
Severity
Moderate
Context
user
Versions
14, 15, 16, 17, 18
Reviewed
2026-06-20

Severity scale: 1 Minimal · 2 Low · 3 Moderate · 4 High · 5 Critical.

Keep going

Related & next steps