critical
free in the CLI
Non-transactional statement mixed into a multi-statement migration
Critical — this fails outright or takes production down.
What it catches
Statements like CREATE INDEX CONCURRENTLY refuse to run in a transaction block. Mixed with other DDL in one migration, either the whole file fails, or the runner drops the transaction and a mid-file error strands the schema between states with no rollback.
Fires on
ALTER TABLE orders ADD COLUMN region text;
CREATE INDEX CONCURRENTLY idx ON orders (region);Do this instead
Split the file: transactional DDL in one migration, and each CREATE INDEX CONCURRENTLY (or other non-transactional statement) alone in its own migration marked to run outside a transaction, so every step either fully commits or fully rolls back.
-- migration 1 (transactional):
SET lock_timeout = '5s';
ALTER TABLE orders ADD COLUMN region text;
-- migration 2 (alone, outside a transaction):
-- CREATE INDEX CONCURRENTLY idx_orders_region ON orders (region);Catch this before it ships
This rule runs locally in the free CLI — or with the full corpus through the hosted service: npx bolvrk check migration.sql