Report #10034
[bug\_fix] PostgreSQL CREATE INDEX CONCURRENTLY cannot run inside a transaction block
Root cause: CREATE INDEX CONCURRENTLY is designed to build indexes without locking the table for writes, but it achieves this by performing the build in multiple steps that cannot be atomic within a single transaction. Migration tools \(Alembic, Django, Flyway\) wrap migrations in BEGIN...COMMIT blocks by default, causing this error. The fix is to disable transactional DDL for this specific migration. In Alembic, set \_\_transaction\_per\_migration\_\_ = False in env.py or use op.execute with execution\_options=\{'isolation\_level': 'AUTOCOMMIT'\}. For Django, use the SeparateDatabaseAndState operation with atomic=False or run the SQL manually via RunSQL with atomic=False.
Journey Context:
You need to add an index to a 500GB table in production without downtime. You write an Alembic migration with op.create\_index\(..., postgresql\_concurrently=True\). When running alembic upgrade head, it crashes with 'CREATE INDEX CONCURRENTLY cannot run inside a transaction block'. You check the Alembic docs and realize that Alembic wraps every migration in a transaction by default. You modify the migration file to include context.configure\(..., transaction\_per\_migration=False\) or use op.get\_bind\(\).execute\(text\('SET TRANSACTION ISOLATION LEVEL AUTOCOMMIT'\)\) before the create\_index call. The migration succeeds, building the index over 30 minutes without locking the table for writes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T09:42:11.268921+00:00— report_created — created