no-drop-column
DROP COLUMN acquires ACCESS EXCLUSIVE lock and may break application queries.
- operation
- Columns
- lock taken
- ACCESS EXCLUSIVE
- remediation
- Manual rewrite
- category
- Data safety
- Breaks a rolling deploy
- Blocks reads
- Blocks writes
What triggers it
Fires on an AT_DropColumn command inside AlterTableStmt.cmds — any ALTER TABLE ... DROP COLUMN ....
What does not
Any AlterTableStmt whose commands don't include AT_DropColumn — ADD COLUMN, ALTER COLUMN TYPE, and so on — is skipped, as is any statement that isn't an AlterTableStmt.
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 catalog update itself is brief under ACCESS EXCLUSIVE, but any application code still selecting, inserting, or updating that column starts failing the instant it commits — that's the real hazard, not the lock duration.
Why it matters
Dropping a column acquires ACCESS EXCLUSIVE lock (briefly) and immediately breaks any query or application code referencing that column. Ensure all code is updated before dropping.
The operation, and the mitigation
Flagged
ALTER TABLE users DROP COLUMN old_field;
Mitigated — still flagged
-- 1. Remove all references in application code -- 2. Deploy code changes -- 3. Then drop the column ALTER TABLE users DROP COLUMN old_field;
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.
Deploy and transaction boundaries
The safe sequence is two separate application deploys: one that removes every code reference to the column, then a later deploy that runs the DROP COLUMN — dropping it in the same deploy as the code change risks a window where old code instances still reference the now-dropped column.
What it assumes
The rule can't see whether application code has actually stopped referencing the column — it flags every DROP COLUMN identically, including one where a prior deploy already removed every reference and the drop is genuinely safe.
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.
ALTER TABLE ... DROP COLUMN is fast.
- verified against
- PostgreSQL 17.10
- last checked
- 2026-08-11
- confidence
- High
Public incidents and write-ups
What the CLI prints
⚠ [MP017] WARNING (line 1) DROP COLUMN "old_field" on "users" takes ACCESS EXCLUSIVE lock. Running application code referencing this column will break immediately. Safe alternative: -- Safe multi-deploy approach: -- Deploy 1: Remove all application code references to "old_field" -- Deploy 2: Drop the column with a short lock timeout SET lock_timeout = '5s'; ALTER TABLE users DROP COLUMN old_field; RESET lock_timeout; Why: DROP COLUMN takes an ACCESS EXCLUSIVE lock and instantly breaks any application code still selecting or inserting that column. Always remove all code references in a prior deploy before dropping the column. Docs: https://migrationpilot.dev/rules/mp017
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 MP017 ALTER TABLE users DROP COLUMN old_field;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP017: false
# or keep it, and downgrade it
rules:
MP017:
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 MP017 in the playground