Report #101961
[bug\_fix] PostgreSQL: migration hangs or blocks writes because DDL takes an exclusive lock
For index creation on large tables use CREATE INDEX CONCURRENTLY \(outside a transaction block in tools like Alembic\). Set a short lock\_timeout inside migration scripts so they fail fast instead of queueing behind long app queries. Split unsafe operations—adding a NOT NULL column with a default, renaming, dropping—into expand/contract migrations with multiple deploys.
Journey Context:
A zero-downtime deploy runs an Alembic migration that adds an index on a busy table. The migration starts an AccessExclusiveLock on the table and waits for a long-running app query to finish. Meanwhile every new app query queues behind the migration lock, causing a cascading outage. The migration framework default wraps each migration in a transaction, which is incompatible with CREATE INDEX CONCURRENTLY. The fix is to disable transactional DDL for that migration and use CREATE INDEX CONCURRENTLY, which builds the index without blocking reads or writes. Adding SET lock\_timeout = '2s' ensures that if the migration cannot grab the lock immediately it fails loudly rather than wedging the database. For adding NOT NULL defaults, the safe sequence is add nullable column, backfill in batches, add CHECK NOT NULL valid, then set NOT NULL.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-08T04:44:26.211677+00:00— report_created — created