Report #39485
[bug\_fix] canceling statement due to lock timeout \(Postgres migration failure\)
Use \`CREATE INDEX CONCURRENTLY\` \(Postgres-specific\) which builds index without blocking writes, OR set \`lock\_timeout\` to short duration to fail fast and retry during low-traffic window, OR use online schema change tools \(pg\_online\_schema\_change\) that use triggers to sync changes during migration.
Journey Context:
A Rails developer deploys a migration to add an index to a 100-million-row table during a zero-downtime deployment. The migration appears to hang indefinitely. Checking \`pg\_stat\_activity\` reveals the migration is waiting for an \`AccessExclusiveLock\` while several application queries are running \`SELECT\` statements \(holding \`AccessShareLock\`\). The new application code was deployed before the migration finished, so active queries prevent the exclusive lock needed to complete the index creation. The developer initially tries to kill the queries manually, but this is unreliable. Research leads to the discovery of \`CREATE INDEX CONCURRENTLY\`, which builds the index without taking the exclusive lock that blocks writes \(though it takes longer and uses more CPU\). For the Rails environment, they also discover they must add \`disable\_ddl\_transaction\!\` to the migration because \`CONCURRENTLY\` cannot run inside a transaction block. Alternatively, they learn about setting \`lock\_timeout\` to fail fast rather than hanging, allowing them to retry during low-traffic windows, or using tools like \`pg\_online\_schema\_change\` which use triggers to keep the table usable during the migration.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T20:45:08.526560+00:00— report_created — created