English for Database Schema Migrations

Master the vocabulary for discussing migration scripts, rollback plans, and zero-downtime schema changes in English.

Schema migrations sit at a genuinely risky intersection of code and production data, so vague language here has real consequences — “we’re updating the database” says nothing about whether the operation locks a table, whether it’s reversible, or whether it needs to run alongside old application code during a rollout. Precise vocabulary matters most in the design review before a migration ships, not after something has already gone wrong.

Key Vocabulary

Migration A versioned, scripted change to a database schema — such as adding a column or creating an index — designed to be applied and tracked incrementally alongside application code changes. Example: “This migration adds a new column with a default value, but on a table this large, that default backfill could take longer than our deployment window allows.”

Rollback (migration rollback) The reverse operation that undoes a migration’s changes, ideally scripted alongside the forward migration so a bad deploy can be reverted cleanly. Example: “This migration doesn’t have a corresponding rollback script — if we need to revert after deploying, we’d have to write one under pressure during an incident.”

Backward-compatible migration A schema change designed so that both the old and new versions of application code can operate correctly against it during a rolling deployment. Example: “We’re making this a backward-compatible migration by adding the new column as nullable first, so old code that doesn’t know about it still works during the rollout.”

Zero-downtime migration A migration strategy, often broken into multiple sequential steps across separate deploys, designed so the database never needs to be taken offline or locked in a way that blocks application traffic. Example: “A zero-downtime migration for this rename means we add the new column, backfill it, deploy code that writes to both, then drop the old column in a later release — not a single atomic rename.”

Table lock A restriction that prevents other operations from reading or writing to a table (or a specific row range) while a migration is running, which can cause visible application slowdowns or timeouts. Example: “Adding this index without the CONCURRENTLY option will hold a table lock for the duration of the build, which would block writes on a table this actively used.”

Backfill The process of populating a new column or table with data for existing rows, often run separately from the schema change itself to avoid locking the table for an extended period. Example: “We’re running the backfill in small batches over several hours rather than in a single transaction, specifically to avoid a long-held lock on this high-traffic table.”

Idempotent migration A migration script designed to be safely run multiple times without causing errors or duplicating changes, useful when a migration might be retried after a partial failure. Example: “We made this migration idempotent by checking whether the column already exists before trying to add it, so a retried deploy doesn’t fail on a duplicate column error.”

Expand-contract pattern A migration strategy for breaking a risky schema change into safe, incremental steps — expanding the schema to support both old and new shapes, migrating usage, then contracting to remove the old shape. Example: “We’re using the expand-contract pattern for this column rename: add the new column, dual-write to both, backfill, switch reads to the new column, then finally drop the old one.”

Common Phrases

In migration review:

  • “This migration doesn’t have a rollback script — can we add one before this merges, even if we hope never to need it?”
  • “Adding this index will hold a table lock for the full build time — should we use a concurrent index build instead, given how much write traffic this table sees?”
  • “This isn’t backward-compatible with the currently deployed application version — during a rolling deploy, some instances would fail against the new schema.”

In standups:

  • “Yesterday I split this schema change into an expand-contract sequence across three deploys; today I’m running the backfill in production in small batches.”
  • “I’m blocked on a migration that needs to run against a table with several hundred million rows — I need to confirm the lock duration is acceptable before we schedule it.”
  • “I finished writing the rollback script for last week’s migration, since we didn’t have one and got lucky that we didn’t need it during the deploy.”

In incident writeups:

  • “The migration held a table lock for twelve minutes, during which write requests to this table queued up and eventually timed out.”
  • “We didn’t have a rollback script ready, so reverting the bad migration required writing and testing one live during the incident, which extended the outage.”
  • “The new column was added as non-nullable without a default, which caused the migration itself to fail against existing rows rather than the deploy failing gracefully.”

Phrases to Avoid

Saying “we’re updating the database” vaguely before a migration ships. Say instead: “this migration adds a nullable column with a backfill running separately, and holds no table lock beyond the initial DDL statement” — the specific mechanics are exactly what a reviewer needs to assess risk.

Saying “it should be fine” without checking lock behavior at scale. Say instead: “let’s confirm the lock duration on a copy of production-sized data before running this against the real table” — assumptions about migration safety that aren’t tested against realistic data volume are a common source of production incidents.

Saying “just rename the column” for a live schema. Say instead: “let’s use the expand-contract pattern here — add the new column, dual-write, backfill, then drop the old one later” — a single atomic rename against a live schema is rarely safe if any code is still deployed against the old name.

Quick Reference

TermHow to use it
migration”This migration adds a new column with a default value.”
rollback”Every migration needs a corresponding rollback script.”
backward-compatible”Adding the column as nullable keeps this backward-compatible during rollout.”
table lock”A concurrent index build avoids holding a table lock.”
backfill”We’re backfilling in small batches to avoid a long lock.”
expand-contract pattern”We’re using expand-contract to safely rename this column.”

Key Takeaways

  • Always specify a migration’s lock behavior and rollback plan in review, not just what it changes structurally.
  • Use the expand-contract pattern by default for any rename or type change on a live table, rather than a single atomic operation.
  • Test migration timing against production-scale data before assuming a migration “should be fine” on a small table.
  • Make migrations idempotent wherever practical, since retried deploys after a partial failure are common enough to plan for.
  • Treat backward compatibility during a rolling deploy as a hard requirement, not an afterthought — old and new application code may run against the schema simultaneously.