ban-drop-schema
DROP SCHEMA permanently removes the schema and all objects within it.
- operation
- Schemas
- lock taken
- ACCESS EXCLUSIVE
- remediation
- Manual rewrite
- category
- Data safety
- Can lose data
What triggers it
Fires on any DropStmt whose removeType is OBJECT_SCHEMA — that is, DROP SCHEMA, with or without CASCADE.
What does not
Any DROP that is not a DropStmt, or one whose removeType is not OBJECT_SCHEMA (DROP TABLE, DROP TYPE, and so on), returns null. Unlike MP022, this rule fires regardless of whether CASCADE is present.
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 SCHEMA takes ACCESS EXCLUSIVE, but as a catalog-level operation the lock itself is typically brief. The real cost is that CASCADE can take every object in the schema with it, unrecoverable without a backup.
Why it matters
DROP SCHEMA removes all tables, views, functions, and other objects in the schema. With CASCADE, this silently destroys everything.
The operation, and the mitigation
Flagged
DROP SCHEMA analytics CASCADE;
Mitigated — still flagged
-- Drop objects explicitly, then schema DROP TABLE analytics.events; DROP SCHEMA analytics;
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 SCHEMA regardless of whether the schema is actually empty or already deprecated; it cannot inspect the real contents, so a safe cleanup of a genuinely empty schema is flagged the same as a destructive one.
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
✗ [MP035] CRITICAL (line 1) DROP SCHEMA "analytics" CASCADE permanently removes the schema and ALL objects within it. This is irreversible without a backup. Safe alternative: -- Verify the schema is empty and unused before dropping: -- SELECT * FROM information_schema.tables WHERE table_schema = 'analytics'; -- SELECT * FROM information_schema.routines WHERE routine_schema = 'analytics'; Why: DROP SCHEMA removes the schema and, with CASCADE, all tables, views, functions, and types it contains. Even without CASCADE it takes an ACCESS EXCLUSIVE lock. Dropped schemas cannot be recovered without a backup restore. Docs: https://migrationpilot.dev/rules/mp035
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 MP035 DROP SCHEMA analytics CASCADE;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP035: false
# or keep it, and downgrade it
rules:
MP035:
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 MP035 in the playground