Open source · Data & Analytics

SQL Migration Safety Checker

Check SQL migrations for lock risk, reversibility and application ordering.

v0.1.0 · Node.js 22+ · MIT

Browse the public repository · View releases

The migration that takes production down is rarely the one that looks dangerous. It is an ALTER TABLE ... ALTER COLUMN ... TYPE in the middle of a file of harmless additions, or a CREATE INDEX somebody forgot to write CONCURRENTLY on, or a table used in 002 and created in 010 because the prefixes were never zero-padded. Those are all visible in the text, and a reviewer reading forty files at the end of a sprint will miss at least one.

This walkthrough uses the tool's public README and checked-in example files. Run the command from a repository checkout with Node.js 22+.

Run the checked-in example

# A careful migration set: no findings, exit 0
node bin/sql-migration-safety-checker.mjs --root examples/clean-migrations --dialect postgres

# A set that needs review: findings on stdout as JSON, summary on stderr, exit 1
node bin/sql-migration-safety-checker.mjs --root examples/risky-migrations --dialect postgres

# A dialect with no rule set: one finding, nothing parsed, exit 2
node bin/sql-migration-safety-checker.mjs --root examples/risky-migrations --dialect mysql

Read the result

stdout always carries the JSON report and nothing else, so it pipes straight into a parser. The human summary goes to stderr, and --json suppresses it. A reader that closes the pipe early — | head, or a parser that bails out — gets one line on stderr and exit 2, never a stack trace: a report that could not be delivered is an execution failure, not a success.

Scope

The size and count bounds are enforced before the work they bound, so a legal-sized input cannot exhaust memory. The time budget is checked cooperatively while walking files, during lexing, and between statements. Every bound is tested from both sides: silent at exactly the limit, and reported at one past it.