no-rename-table
Renaming a table breaks all queries, views, and foreign keys referencing it.
- operation
- Tables
- lock taken
- ACCESS EXCLUSIVE
- remediation
- Manual rewrite
- category
- Data safety
- Breaks a rolling deploy
What triggers it
Fires on a RenameStmt whose renameType is OBJECT_TABLE — that is, ALTER TABLE ... RENAME TO ....
What does not
Any RENAME that targets something other than the table itself — a column, index, constraint, or sequence rename — carries a different renameType and returns null.
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
ACCESS EXCLUSIVE is held only briefly for the catalog rename. The danger is not lock duration — it is that every query, view, function, and foreign key referencing the old name breaks the instant the rename commits, with no fallback.
Why it matters
Table renames take effect immediately and break all running queries, views, stored procedures, and application code that reference the old name.
Unsafe, and safe
Flagged
ALTER TABLE users RENAME TO accounts;
Safe alternative
-- Create new table, migrate data, update app code, drop old CREATE TABLE accounts (LIKE users INCLUDING ALL); -- Migrate data and update references
What it assumes
Assumes application code, views, or functions actually reference the table by its old name; a table not yet referenced anywhere, such as one added and renamed within the same release, can be renamed safely despite the warning.
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 ... RENAME COLUMN is instant, holds a lock for microseconds, rewrites nothing, and is fully reversible.
- verified against
- PostgreSQL 17.10
- last checked
- 2026-08-11
- confidence
- High
Public incidents and write-ups
What the CLI prints
⚠ [MP028] WARNING (line 1) Renaming table "users" to "accounts" will break all application queries, views, and foreign keys referencing the old name. Safe alternative: -- Step 1: Create a view with the old name pointing to the new table -- (or use the expand-contract pattern): -- CREATE VIEW users AS SELECT * FROM accounts; -- Step 2: Update application code to use "accounts" -- Step 3: Drop the compatibility view after all code is updated -- DROP VIEW users; Why: Renaming a table takes an ACCESS EXCLUSIVE lock and instantly breaks every application query, view, function, foreign key, and trigger referencing the old name. Unlike renaming a column, there is no pg_attribute fallback. Use the create-copy-swap pattern for zero-downtime renames. Docs: https://migrationpilot.dev/rules/mp028
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 MP028 ALTER TABLE users RENAME TO accounts;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP028: false
# or keep it, and downgrade it
rules:
MP028:
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 MP028 in the playground