Skip to content
Sarj Code Standards

invalid-concurrent-ddl

Keep concurrent PostgreSQL DDL in supported execution contexts.

Why

PostgreSQL rejects concurrent index creation and removal inside a transaction block. Concurrent index removal also rejects multiple targets and CASCADE, and a concurrent materialized-view refresh cannot request WITH NO DATA.

Fix

Run concurrent index commands outside a transaction, using transaction:false for the relevant dbmate section. Drop one index per concurrent command without CASCADE. Choose either a concurrent populated refresh or a nonconcurrent WITH NO DATA refresh. Preserve deployment and atomicity requirements when changing transaction boundaries.

Examples

Before — flagged A concurrent index build cannot execute in the runner's transaction
migrations/001_index.sql
-- migrate:up
CREATE INDEX CONCURRENTLY account_email ON account (email);
After — preferred The runner explicitly executes the concurrent index outside a transaction
migrations/001_index.sql
-- migrate:up transaction:false
CREATE INDEX CONCURRENTLY account_email ON account (email);