Can I add an enum value and use it in the same migration?
Enum value added inside a multi-statement migration
Warning: this works, but blocks traffic or rewrites data at scale.
What happens
Adding an enum value has transaction restrictions: before Postgres 12 it errors inside a transaction block, and on 12+ the new value is unusable until the transaction commits. A migration runner that wraps the file in one transaction either fails outright or fails on the first statement that uses the new value.
Why it is dangerous on a populated table
It completes, but the time it holds its lock or rewrites rows scales with the table, and on a busy one that is long enough for traffic to queue.
Fires on
ALTER TYPE order_status ADD VALUE 'archived';
UPDATE orders SET status = 'archived';The safe pattern
Put ALTER TYPE ... ADD VALUE alone in its own migration so it commits before anything uses the value; statements that use the new value go in a later migration. On Postgres 12+ the statement is allowed inside a transaction, but the value stays unusable until that transaction commits, the split fixes both eras.
-- migration 1 (single statement, commits on its own):
ALTER TYPE order_status ADD VALUE IF NOT EXISTS 'archived';
-- migration 2 (later): statements that USE 'archived'Fixtures
The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.
Fires (1)
ALTER TYPE order_status ADD VALUE 'archived';
UPDATE orders SET status = 'archived' WHERE closed_at < now() - interval '1 year';Stays silent (1)
ALTER TYPE order_status ADD VALUE 'archived';How to check locally
This rule runs in the hosted service on Startup and above: add --remote with a team token, or use the GitHub Action. No install, nothing leaves your machine:
npx bolvrk check migration.sql --remote