ban-drop-table
DROP TABLE permanently removes the table and all its data.
- operation
- Tables
- lock taken
- ACCESS EXCLUSIVE
- remediation
- Manual rewrite
- category
- Data safety
- Can lose data
What triggers it
Fires on any DropStmt whose removeType is OBJECT_TABLE — that is, DROP TABLE, with or without CASCADE.
What does not
Any DROP statement that is not a DropStmt, or one that does not target OBJECT_TABLE (DROP INDEX, DROP TYPE, DROP VIEW, and so on), returns null before the message is built.
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
DROP TABLE takes ACCESS EXCLUSIVE for the duration of the drop. On a normal table this is typically fast, metadata-level work — the real danger is not lock duration, it is that the drop is instant and unrecoverable without a backup.
Why it matters
DROP TABLE is irreversible and acquires ACCESS EXCLUSIVE lock. All data, indexes, constraints, and triggers are permanently destroyed. Consider renaming the table first as a soft-delete.
The operation, and the mitigation
Flagged
DROP TABLE users;
Mitigated — still flagged
-- Soft-delete: rename first, drop later after verification ALTER TABLE users RENAME TO users_deprecated; -- After confirming no dependencies: DROP TABLE users_deprecated;
This operation is irreversible, so there is no syntax that makes it safe. The second block is what care looks like — and MigrationPilot still flags it. The mitigation is process: confirm nothing reads the object, keep a way back, and do it in a window where you can watch.
What it assumes
Fires on every DROP TABLE unconditionally, including drops of genuinely obsolete or empty tables in a controlled cleanup migration — it has no way to distinguish those from an accidental drop of a live table.
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
✗ [MP026] CRITICAL (line 1) DROP TABLE "users" permanently removes the table and all its data. This is irreversible and takes an ACCESS EXCLUSIVE lock. Safe alternative: -- Step 1: Rename the table (keeps data as backup) ALTER TABLE users RENAME TO users_deprecated; -- Step 2: After confirming no application depends on it, drop later -- DROP TABLE users_deprecated; Why: DROP TABLE is irreversible. It permanently deletes the table, all rows, indexes, constraints, triggers, and policies. In production, this means instant data loss. Prefer renaming the table first, keeping it as a backup, then dropping later after confirming no dependencies. Docs: https://migrationpilot.dev/rules/mp026
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 MP026 DROP TABLE users;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP026: false
# or keep it, and downgrade it
rules:
MP026:
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 MP026 in the playground