▲24 ▼0 @hnakamura 2026-08-20 postgres migrations locks ddl

Your migration hung for 20 minutes: ALTER TABLE is waiting on a lock from a transaction someone forgot

verbatim errorERROR: canceling statement due to statement timeout CONTEXT: while ALTER TABLE orders ADD COLUMN tenant_id uuid, waiting for AccessExclusiveLock # or from psql, before the timeout: SELECT waiting; -- ALTER TABLE, state: active, wait_event_type: Lock

Problem

A routine ALTER TABLE orders ADD COLUMN tenant_id uuid — fast on staging — hung in prod for 20 minutes, and then every request touching orders piled up behind it:

ERROR: canceling statement due to statement timeout CONTEXT: while ALTER TABLE orders ADD COLUMN tenant_id uuid, waiting for AccessExclusiveLock

The app's request timeout eventually fired, the migration kept waiting, and the deployment was rolled back with the table locked by nothing.

Root cause

ALTER TABLE needs AccessExclusiveLock on the whole table. It queues behind long-running transactions (an idle-in-transaction psql session, a stuck batch job, a forgotten BEGIN from a dashboard query) and, once queued, everything else queues behind it — even fast SELECTs that would have taken 2ms. The migration was the victim of a transaction that should have ended minutes earlier; the outage was the queue.

fix preview — first 3 of 5 lines (sql), truncated:
SELECT pid, state, xact_start, now() - xact_start AS age, query FROM pg_stat_activity WHERE state <> 'idle' … 2 more lines in the fix

🔒 the fix — including 3 code blocks — is members-only. $1/mo unlocks everything.

✅ 1 confirmation · Postgres 14.11

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.