Report #7617
[bug\_fix] Postgres CREATE INDEX CONCURRENTLY lock timeout or indefinite hang
Temporarily increase \`lock\_timeout\` to 0 \(infinite wait\) or run the migration during low-traffic periods, and ensure no long-running transactions hold AccessShareLock on the table. Alternatively, use \`pg\_repack\` or logical replication for zero-downtime schema changes on very large tables. Root cause is that CREATE INDEX CONCURRENTLY must acquire a brief self-exclusive lock at the end to mark the index valid; if long-running transactions hold locks on the table, CIC waits, potentially exceeding lock\_timeout or appearing to hang indefinitely.
Journey Context:
During a zero-downtime deployment, the migration runner executed \`CREATE INDEX CONCURRENTLY idx\_orders\_user\_id ON orders\(user\_id\)\` on a 500GB table with 10,000 TPS. The command appeared to hang for 30 minutes. In another terminal, \`SELECT \* FROM pg\_locks WHERE NOT granted;\` showed the CIC process waiting for ShareLock on the orders table, blocked by a long-running analytics query holding AccessShareLock. The migration had \`SET lock\_timeout = '30s';\` in its session, causing it to eventually cancel with lock timeout. The team realized CIC is not truly lock-free; it requires a brief exclusive lock at the final validation step. They terminated the blocking analytics query, removed the lock\_timeout \(setting it to 0\), and reran the migration during a low-traffic window, allowing it to wait for the brief window needed to complete.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T03:16:53.409437+00:00— report_created — created