ban-truncate-cascade
TRUNCATE CASCADE silently truncates all tables referenced by foreign keys.
- operation
- Tables
- lock taken
- no table lock
- remediation
- Manual rewrite
- category
- Data safety
- Can lose data
What triggers it
Fires on a TruncateStmt whose behavior is DROP_CASCADE — that is, TRUNCATE ... CASCADE.
What does not
A plain TRUNCATE without CASCADE returns null — only the DROP_CASCADE behavior is flagged, so truncating a table with no dependent foreign keys never triggers this rule.
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
The rule does not evaluate lock behavior. Its concern is the CASCADE fan-out: every table with a foreign key pointing at the truncated table gets emptied too, recursively, with nothing in the statement listing which tables that includes.
Why it matters
TRUNCATE CASCADE follows FK relationships and empties referencing tables too. This can silently destroy data across your entire schema.
Unsafe, and safe
Flagged
TRUNCATE users CASCADE;
Safe alternative
-- Truncate explicitly without CASCADE TRUNCATE users; -- Or use DELETE with WHERE for safer data removal
What it assumes
Assumes the foreign-key graph is wide enough that CASCADE reaches unintended tables; on a target with no incoming foreign keys, TRUNCATE CASCADE behaves identically to a plain TRUNCATE and the warning does not really apply.
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.
DROP TABLE is the only operation in this handbook with no recovery path.
- verified against
- PostgreSQL 17.10
- last checked
- 2026-08-11
- confidence
- Medium
PostgreSQL manual
What the CLI prints
✗ [MP036] CRITICAL (line 1) TRUNCATE users CASCADE silently truncates all tables with foreign key references. This can destroy data across many related tables. Safe alternative: -- Truncate specific tables explicitly in dependency order: -- TRUNCATE users; -- Or use DELETE with WHERE clauses for safer, auditable data removal. Why: TRUNCATE CASCADE removes all rows not only from the target table but from every table that references it via foreign keys, recursively. This can silently wipe data from dozens of tables. Always truncate specific tables explicitly. Docs: https://migrationpilot.dev/rules/mp036
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 MP036 TRUNCATE users CASCADE;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP036: false
# or keep it, and downgrade it
rules:
MP036:
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 MP036 in the playground