How to Review a Database Migration PR
Code review is a solved problem. Linters catch style issues. Tests catch logic bugs. Type checkers catch interface mismatches. But database migrations? They still get the "looks fine, ship it" treatment — until a missing index tanks query performance, or a dropped column breaks a background job at 2 AM.
This post is a practical checklist for reviewing database migration pull requests. It covers what to look for, what tools to use, and how to catch the changes that linters and tests will never find.
🔍 Diff schemas in 1 click
Paste old and new schema files to see exactly what changed — tables, columns, indexes, constraints, and more.
Open Schema Diff →Why Migration PRs Need Special Treatment
Database migrations are different from normal code changes in three critical ways:
- They run in production once. You can't "revert and redeploy" a migration the same way you revert a buggy API endpoint. Rolling back a migration is a separate, often manual operation.
- They hold locks. An
ALTER TABLEon a large table can lock reads and writes for minutes or hours. Some operations rebuild the entire table. Reviewers need to know which changes are fast and which are not. - They affect multiple systems. A dropped column breaks not just the app, but also ETL pipelines, analytics dashboards, third-party integrations, and background workers. The PR author may not even know about all the consumers.
Because of this, migration PRs deserve a review process that goes deeper than "does this SQL compile?"
The 5-Minute Migration PR Checklist
Here's the checklist every migration PR should pass before merging:
- Breaking changes: Are any tables or columns being dropped? Are foreign keys being removed? Is a
NOT NULLbeing added without a default? - Performance impact: Does the migration add an index? Does it modify a large table? Will it hold locks? Is there a note about estimated runtime?
- Rollback plan: Is there a down migration? Does it actually restore the previous state, or does it leave the database in a broken intermediate state?
- Schema correctness: Does the final schema match the intent? Are indexes named consistently? Are foreign keys pointing to the right columns?
- Cross-system impact: Are there notes about downstream consumers? Does the PR description mention analytics, exports, or integrations that depend on the changed schema?
If the PR touches a table with more than a million rows, add a sixth item: Has this been tested on a copy of production data? Some migrations that run in seconds on a developer laptop take hours in production.
Red Flags: Changes That Should Block Merge
These changes should trigger an immediate "request changes" review:
| Change | Why It's Dangerous | What To Ask |
|---|---|---|
DROP TABLE or DROP COLUMN |
Data loss. Breaks downstream consumers. | "Is this column still referenced by any code, job, or report?" |
ALTER COLUMN ... TYPE |
May truncate data or change behavior. | "Will existing data fit the new type? Is there a cast strategy?" |
ADD NOT NULL without DEFAULT |
Fails on existing NULL rows. | "What should the default value be? Two-step migration?" |
| Removing an index | Query performance regression. | "Is this index unused, or is it used by a report/job?" |
| Removing a foreign key | Referential integrity loss. | "Is application code handling orphaned rows?" |
How to Actually See the Schema Changes
Reading the migration file is not enough. Migration files show intent, not outcome. A migration might add a column, but does the final CREATE TABLE look right? Did the author forget an index? Is the foreign key constraint named correctly?
The best way to review a migration PR is to diff the before and after schema. Here's the workflow:
- Export the current schema from
main(or your target branch) - Export the schema after applying the migration
- Diff them with a semantic schema diff tool
- Review the changes as a structured list, not a wall of SQL
With SchemaLens, you can do this in under a minute. Paste the old schema in the left panel, the new schema in the right panel, and get an instant breakdown of what changed:
Summary: 1 table modified, 2 columns added, 1 index added Modified: orders + Column: discount_code VARCHAR(20) + Column: refunded_at TIMESTAMP NULL + Index: idx_orders_discount_code Migration SQL: ALTER TABLE orders ADD COLUMN discount_code VARCHAR(20); ALTER TABLE orders ADD COLUMN refunded_at TIMESTAMP NULL; CREATE INDEX idx_orders_discount_code ON orders(discount_code);
This is vastly easier to review than reading a 300-line pg_dump output or trying to mentally simulate what a migration file does.
⚡ Diff schemas in seconds
Paste two schemas and see exactly what changed — no signup required.
Open SchemaLens →Automating the Review with CI
For teams that review a lot of migrations, automate the diff. The SchemaLens GitHub Action can post a schema diff summary as a PR comment every time a .sql file changes. Reviewers see the semantic diff right in the PR thread without running any commands.
The Action can also fail the build when breaking changes are detected, turning the checklist above into an automatic gate:
name: Schema Diff
on:
pull_request:
paths: ['**/*.sql', 'db/migrations/**']
jobs:
diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: SchemaLens Diff
run: |
node ci/schemalens-diff.js schema_base.sql schema.sql \
--dialect postgres --format markdown --output report.md
This doesn't replace human judgment — it augments it. The reviewer still decides whether the change is safe, but they now have structured data instead of a gut feeling.
Reviewing Rollback Migrations
Every up migration needs a down migration. But a down migration is only useful if it actually works. Here's what to check:
- Does the down migration reverse every change in the up? If the up adds two columns and an index, the down should drop both columns and the index.
- Will the down migration fail on production data? Dropping a
NOT NULLcolumn is easy. Adding it back is not — existing rows may now be NULL. - Is the down migration tested? Run it against a copy of production data. Some down migrations only work on empty databases.
"We never roll back" is not a valid excuse for skipping down migrations. The one time you need to roll back at 3 AM during an outage, you'll be glad you have one.
The Migration PR Template
Add this template to your repository's .github/pull_request_template.md or your code review tool:
## Database Migration Checklist - [ ] This migration has been tested on a copy of production data - [ ] Estimated runtime on production: ___ minutes - [ ] This migration acquires locks: Yes / No - [ ] Down migration is included and tested - [ ] Breaking changes are documented in PR description - [ ] Downstream consumers (reports, jobs, integrations) have been notified
Forcing authors to think through these questions before opening the PR catches 80% of migration issues before a reviewer even looks at the code.
Summary
- Migration PRs need a different review process than code PRs because they run once, hold locks, and affect multiple systems.
- Always check for breaking changes, performance impact, rollback plans, schema correctness, and cross-system impact.
- Diff the before and after schema semantically — reading the migration file alone is not enough.
- Use CI automation to post diff reports as PR comments and flag breaking changes automatically.
- Require down migrations and test them against realistic data.
- Use a PR template to force authors to think through runtime, locks, and downstream impact before requesting review.
Make migration review effortless
Diff schemas, generate migrations, and catch breaking changes — all in your browser.
Open SchemaLens → Add GitHub Action →