MP035critical

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

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

What the CLI prints

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

.migrationpilotrc.yml
rules:
  MP035: false

# or keep it, and downgrade it
rules:
  MP035:
    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 MP035 in the playground

Related rules