Report #8302
[bug\_fix] canceling statement due to lock timeout during migration
Use \`CREATE INDEX CONCURRENTLY\` \(or Rails \`algorithm: :concurrently\`\) for index creation, and set \`lock\_timeout\` in migration scripts to fail fast instead of hanging. Root cause: Postgres \`CREATE INDEX\` requires \`AccessExclusiveLock\` on the table, blocking reads and writes. Long-running queries \(reports, analytics\) hold \`AccessShareLock\`, preventing the exclusive lock acquisition. Without \`lock\_timeout\`, migration hangs indefinitely. \`CREATE INDEX CONCURRENTLY\` uses \`ShareLock\` \(allows reads\) and builds index in background passes, avoiding exclusive locks but taking longer and using more CPU.
Journey Context:
Rails app with 100M row \`orders\` table. Deployment runs \`add\_index :orders, :user\_id\` during business hours. Migration hangs for 30 minutes, then CI kills it. Investigation reveals \`CREATE INDEX\` waiting for \`AccessExclusiveLock\` on \`orders\`. Querying \`pg\_stat\_activity\` shows 20 active queries from reporting dashboard holding \`AccessShareLock\` for 5\+ minutes. Developer tries running migration at 3 AM but cron jobs still cause conflicts. Reads about \`lock\_timeout\` and sets \`ActiveRecord::Base.connection.execute\("SET lock\_timeout = '10s'"\)\` before migration. Now migration fails fast with 'canceling statement due to lock timeout'. Realizes they need \`CREATE INDEX CONCURRENTLY\`. Switches to \`add\_index :orders, :user\_id, algorithm: :concurrently\`. Migration takes 20 minutes but doesn't block queries, completing successfully during peak traffic.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T05:11:25.499718+00:00— report_created — created