Report #11799
[bug\_fix] ERROR: canceling statement due to lock timeout \(migration hangs\)
The root cause is that PostgreSQL's DDL statements \(ALTER TABLE, CREATE INDEX CONCURRENTLY excepted\) require AccessExclusiveLock on the target table, which conflicts with any other lock \(even ACCESS SHARE from SELECT\). By default, \`lock\_timeout\` is 0 \(infinite wait\), causing migrations to hang indefinitely if any long-running query holds a lock. If \`lock\_timeout\` is set too low, migrations fail fast. The fix is to implement a 'safe migration' pattern: \(1\) Set a moderate \`lock\_timeout\` \(e.g., 5s\) in the migration to fail fast rather than hang, \(2\) Before migrating, query \`pg\_stat\_activity\` to identify and gracefully terminate \(or wait for completion of\) long-running queries holding locks on the target table, \(3\) For zero-downtime, use \`CREATE INDEX CONCURRENTLY\` \(which doesn't block writes\) and tools like \`pg\_repack\` or \`pt-online-schema-change\` for ALTER TABLE operations that avoid long-lived exclusive locks by creating a shadow table and using triggers.
Journey Context:
You're running a zero-downtime deployment of a Rails application using PostgreSQL. You use ActiveRecord migrations with \`strong\_migrations\` gem. During deployment, the migration pod starts, logs 'Migrating...', then hangs for 10 minutes until Kubernetes kills it. You check \`pg\_stat\_activity\` and see the migration query is \`LOCK TABLE users IN ACCESS EXCLUSIVE MODE\` and is blocked by another query \`SELECT \* FROM users WHERE id = 5\`. That SELECT is from a long-running Sidekiq job. The rabbit hole involves realizing that ActiveRecord migrations acquire AccessExclusiveLock on tables to alter them, but the default \`lock\_timeout\` is 0 \(wait forever\). You try setting \`SET lock\_timeout = '5s'\` in the migration, but now it fails immediately with 'canceling statement due to lock timeout'. You realize you need to stop the long-running queries first \(using \`pg\_terminate\_backend\` or graceful shutdown\), or use \`pg\_repack\`/\`pt-online-schema-change\` style online migrations that don't need long exclusive locks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T14:19:14.570797+00:00— report_created — created