awesome-everything RU
↑ Back to the climb

Databases

What a schema migration is and why it replaces ad-hoc DDL

Crux A migration is a versioned, ordered SQL script that changes the database schema in lock-step with the application code that depends on it.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at junior altitude — the surface
◷ 8 min

Otto wants to add a phone column to users. He opens psql and runs ALTER TABLE users ADD COLUMN phone TEXT. Three months later a new engineer joins, clones the repo, and gets errors because their database has no phone column. Nobody knows what to change. The schema has drifted.

The problem with ad-hoc DDL

Running ALTER TABLE directly in psql works once, on one machine, for one engineer. The moment a second environment exists — staging, CI, a teammate’s laptop — the schema diverges silently. Nobody tracks what changed or when. Forward reproducibility is gone.

A migration file encodes the change as a named, ordered artefact:

-- migrations/20260514_add_user_phone.sql
ALTER TABLE users ADD COLUMN phone TEXT;

The migration tool records which files have run in a schema_migrations table. A new engineer running prisma migrate dev or flyway migrate gets all pending migrations applied in order. The database reaches the same known state on every machine.

Migrations are versioned like commits

Git commitMigration file
Moves codebase from state N to N+1Moves schema from state N to N+1
Ordered by timestamp/hashOrdered by version prefix (timestamp or V1/V2)
Applied once; immutable after mergeApplied once per database; never edited after deploy
Reviewable as a diff in a PRReviewable SQL in a PR, linted by Squawk or Atlas
Reproducible: git clone + history = same codeReproducible: migrate up from blank = same schema

Deploy order matters

The database schema and the application code that uses it must be compatible at every moment of the deploy, because production traffic does not pause for your migration.

Two rules:

  1. Additive change (new column the new code reads): run the migration before deploying code. Old code ignores the new column; new code finds it ready.
  2. Removal (drop a column the old code reads): deploy new code first, wait for old code to drain, then run the migration. Otherwise old code queries a non-existent column and fails.

Single-transaction migrations that drop or rename columns in one step are the classic deploy-coupled bug; the fix is to split changes into safe additive steps — covered in lesson 05.

Why this works

Why do migration tools use a schema_migrations table instead of comparing the live schema against the desired schema? Diffing schemas is error-prone — two schemas can look identical structurally while having different indexes, constraints, or permissions. Tracking which migration files have run is simpler, auditable, and survives database restores.

Quiz

Why use migration files instead of running ALTER TABLE directly in psql?

Quiz

A migration adds a new column that the new application code reads. What is the correct deploy order?

Order the steps

Order the lifecycle steps of a production schema migration:

  1. 1 Write the migration SQL file with a version prefix (timestamp or V-number)
  2. 2 Open a PR: SQL is reviewed, linted by Squawk or Atlas CI
  3. 3 Merge the PR — migration file is now in version control
  4. 4 CI runs migration against staging; tests pass
  5. 5 Migration runs on production before the new code deploys
  6. 6 Application code that depends on the schema change is deployed
  7. 7 Migration tool records the file as applied in schema_migrations
Complete the analogy

Fill in the blank: a database migration is to schema changes what a git ___ is to code changes — a versioned, ordered, reviewable unit that moves the system from state N to state N+1.

Recall before you leave
  1. 01
    In two sentences: what is a schema migration and what problem does it solve over ad-hoc DDL?
  2. 02
    Why does the deploy order of migration vs app code matter, and what is the rule for an additive change?
  3. 03
    What does the schema_migrations table contain and why is it better than diffing the schema?
Recap

A migration is a versioned SQL file that moves the database schema from state N to N+1 and is recorded in the schema_migrations table once applied. Running ALTER TABLE ad-hoc works once but leaves no history and diverges environments silently. Migration tools (Prisma Migrate, Flyway, golang-migrate, Atlas) apply pending files in order on every environment so the schema is always reproducible from blank. Deploy order is not optional: for additive changes, run the migration first so the schema is ready when new code lands.

Connected lessons
appears again in140
Continue the climb ↑ADD COLUMN: instant in PG 11+ vs rewrite in older Postgres
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.