Schema Diff

Paste two SQL CREATE TABLE statements or JSON schemas — see a visual diff and get a generated migration script.

Presets:
Add column users table: add email_verified
Refactor table products: rename, change types, drop
JSON schema evolve API response: add fields, tighten
Orders v2 New FK, index, NOT NULL changes
Before v1
After v2
Paste schemas above and click Generate Diff.

Why Schema Migrations Matter

Databases enforce schemas at write time. Changing a schema without a migration leaves existing rows invalid or the app's ORM out of sync — causing 500 errors in production. Migrations are the contract between code version and data version.

Safe vs Unsafe Operations

Safe: adding a nullable column, adding an index concurrently, adding a table. Unsafe: dropping a column, renaming a column (breaks old code), changing a type, adding NOT NULL without a default (locks table on large datasets).

Zero-Downtime Migrations

Expand-contract pattern: (1) add new column, (2) deploy code that writes to both old and new, (3) backfill old rows, (4) deploy code that reads new column, (5) drop old column. Each step is independently deployable and rollback-safe.

Migration Tooling

Flyway and Liquibase (Java/SQL-first). Alembic (Python/SQLAlchemy). Prisma Migrate (Node.js). Active Record Migrations (Rails). All track applied migrations in a schema_migrations table.

Versioning Strategy

Sequential integers (V1, V2...) work for solo teams; timestamps (20240512_143000) avoid merge conflicts on feature branches. Never edit an already-applied migration — always add a new one.

Rollback Strategy

Write a down migration for every up. Dropping columns in up = no rollback possible without restoring from backup. This is why expand-contract matters: you can always revert before the drop step.

JSON Schema Evolution

JSON Schema is additive: adding optional fields is backward-compatible. Adding required fields, removing fields, or tightening validation breaks existing producers/consumers. Use additionalProperties: false carefully — it's a foot-gun in API versioning.

Index Migrations

CREATE INDEX takes a full table lock in most databases. Use CREATE INDEX CONCURRENTLY (PostgreSQL) or online DDL (MySQL 8+) for production tables. Monitor index build progress via pg_stat_progress_create_index.