ban-disable-trigger
DISABLE TRIGGER breaks replication, audit logs, and FK enforcement.
- operation
- Triggers
- lock taken
- no table lock
- remediation
- Manual rewrite
- category
- Data safety
- Breaks replication
What triggers it
The AT_DisableTrigAll or AT_DisableTrigUser subtype of ALTER TABLE — ALTER TABLE ... DISABLE TRIGGER ALL or ... DISABLE TRIGGER USER.
What does not
ALTER TABLE ... DISABLE TRIGGER <name> targeting one specific trigger by name produces neither subtype and passes through, as does any AlterTableStmt with no cmds or no relation.relname, or any table alteration that doesn't touch triggers at all.
Where it applies
Applies to every PostgreSQL version MigrationPilot targets. It works on the SQL text alone — no database connection needed.
The lock, and what it blocks
No lock is named in the source — the danger isn't blocking, it's that once triggers are off, logical replication (which relies on triggers internally), audit logging, and foreign-key enforcement all silently stop working until something re-enables them.
Why it matters
ALTER TABLE DISABLE TRIGGER ALL/USER turns off all triggers on the table. This breaks logical replication (which uses triggers internally), disables audit logging triggers, and bypasses foreign key enforcement. If the session crashes before re-enabling triggers, they remain disabled permanently.
Unsafe, and safe
Flagged
ALTER TABLE users DISABLE TRIGGER ALL;
Safe alternative
-- Disable only a specific trigger temporarily ALTER TABLE users DISABLE TRIGGER my_audit_trigger; -- ... perform operation ... ALTER TABLE users ENABLE TRIGGER my_audit_trigger;
What it assumes
The rule assumes the table has triggers whose loss matters — replication, audit, FK enforcement — which won't be true for every table. It also can't tell whether the same session re-enables triggers later; it flags the disable unconditionally.
What backs this rule
Every rule is a claim about PostgreSQL, so it carries what the claim rests on: a handbook chapter that cites the manual, the incidents that put it there, and the version it was last checked against.
Two migrations that look local to one table, and are not: dropping a primary key, and disabling triggers.
- verified against
- PostgreSQL 17.10
- last checked
- 2026-08-11
- confidence
- High
PostgreSQL manual
Public incidents and write-ups
What the CLI prints
✗ [MP064] CRITICAL (line 1) DISABLE TRIGGER ALL on "users" breaks replication, audit logs, and FK enforcement. Use targeted trigger disabling or restructure the migration. Why: ALTER TABLE DISABLE TRIGGER ALL/USER turns off all triggers on the table. This breaks logical replication (which uses triggers internally), disables audit logging triggers, and bypasses foreign key enforcement. If the session crashes before re-enabling triggers, they remain disabled permanently. Docs: https://migrationpilot.dev/rules/mp064
Generated by running the CLI's own formatter over the flagged example above, so it is the text the tool actually produces. A real run also reports the other rules that fire on the same statement; those blocks are left out here.
Turning it off
For one statement, put a comment on the line before it:
-- migrationpilot-disable MP064 ALTER TABLE users DISABLE TRIGGER ALL;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP064: false
# or keep it, and downgrade it
rules:
MP064:
severity: warningTry it
Open this rule's flagged example in the playground. It runs in your browser — edit it and watch the finding appear and disappear.
Run MP064 in the playground