/migration-safe
Catch dangerous migrations before they hit production.
Usage
/migration-safe migrations/20260101_add_status.sql
/migration-safe # last unapplied migration
/migration-safe --all # all pending
What it checks
Locking
ALTER TABLE ADD COLUMNwith default → table rewrite on Postgres < 11ADD CONSTRAINT NOT NULLwithoutNOT VALIDfirst- Long-running indexes without
CONCURRENTLY ALTER COLUMN TYPEthat requires full rewrite
Backward compat
- Renaming or dropping columns still referenced by old app code
- Type changes that break existing queries
- Reordering enums (Postgres allows but ORMs often don't)
Data integrity
- Missing
NOT NULLdefaults → rows with NULL after backfill - Foreign key cascades that could nuke unrelated data
- Triggers that aren't transactional
Reversibility
- Missing
downmigration - Down migration that loses data silently
Output
For each issue:
- Severity (will break prod / risky / inefficient / minor)
- What goes wrong (concrete: "5min downtime on tables > 1M rows")
- Safe alternative (e.g. expand-and-contract pattern)
Rules
- Adapt to the DB engine (Postgres / MySQL / SQLite — different gotchas)
- For Postgres, prefer
CREATE INDEX CONCURRENTLY,SET NOT NULL ... NOT VALID + VALIDATE - Suggest a multi-step rollout if a migration can't be safe in one shot