MP036critical

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

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

What the CLI prints

migrationpilot analyze migration.sql
✗ [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:

.migrationpilotrc.yml
rules:
  MP036: false

# or keep it, and downgrade it
rules:
  MP036:
    severity: warning

Try 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

Related rules