What happens to foreign keys when a migration disables all triggers?
Triggers disabled: with ALL, foreign keys stop being enforced
Warning: this works, but blocks traffic or rewrites data at scale.
What happens
DISABLE TRIGGER ALL includes the system triggers that enforce foreign keys, writes made while it is off can violate referential integrity permanently, and re-enabling does not re-check them. Disabling a single trigger silently skips whatever logic it carried.
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 TABLE orders DISABLE TRIGGER ALL;The safe pattern
Never DISABLE TRIGGER ALL: it turns off the system triggers that enforce foreign keys, and re-enabling does not re-check rows written meanwhile. If one user trigger must be bypassed, name it, keep the window to a single bounded operation, and re-enable it in the same migration. Better: make the trigger itself cheap or conditional so it never needs disabling.
-- Target one named trigger, re-enable in the same migration:
-- ALTER TABLE orders DISABLE TRIGGER orders_audit_trigger;
-- ... one bounded data fix ...
-- ALTER TABLE orders ENABLE TRIGGER orders_audit_trigger;
-- FK enforcement (system triggers) stays on throughoutFixtures
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 (2)
ALTER TABLE orders DISABLE TRIGGER ALL;ALTER TABLE orders DISABLE TRIGGER audit_orders;Stays silent (1)
ALTER TABLE orders ENABLE TRIGGER audit_orders;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