The PostgreSQL administration field guideField notes · Runbooks · Free certification
practitioner16 minute lesson

Locks, blockers, and wait events

Read a blocking chain, identify its root, and choose a response based on impact and transaction ownership.

Progress stays on this device

Mental model

A blocked session is usually a symptom. The useful object is the blocking chain: which backend waits, which backend holds the conflicting lock, how long each transaction has existed, and what business work each session owns. Resolve the root rather than terminating every waiter.

What healthy usually looks like

  • Lock waits are brief, attributable, and do not form growing chains.
  • Transactions remain short enough that row versions and locks are released predictably.
  • Schema changes use lock-aware deployment patterns and explicit timeouts.

Ask the database a bounded question

Diagnostic query

Find blocked sessions and blocker PIDs

List sessions currently blocked by other backends and show the age of their query and transaction.

SELECT
  blocked.pid AS blocked_pid,
  pg_blocking_pids(blocked.pid) AS blocking_pids,
  blocked.wait_event_type,
  blocked.wait_event,
  now() - blocked.query_start AS blocked_for,
  now() - blocked.xact_start AS transaction_age,
  left(blocked.query, 140) AS blocked_query
FROM pg_stat_activity AS blocked
WHERE cardinality(pg_blocking_pids(blocked.pid)) > 0
ORDER BY blocked_for DESC;
low observation cost

Read the output

  1. Draw the chain from root blocker to leaf waiters and attach business ownership before terminating anything.
  2. Distinguish a necessary short lock from an abandoned transaction that has stopped making progress.
  3. Use `lock_timeout` for lock-sensitive operations; it limits waiting, not statement runtime after the lock is acquired.

Common traps

  • Killing the longest waiter instead of the root blocker.
  • Running a DDL change without understanding the lock mode and queueing effect.
  • Treating `idle in transaction` as harmless because no query is currently active.

Check your reasoning

Ten sessions are blocked by one idle-in-transaction backend. What do you inspect first?

Related runbooks

Sources