Skip to content

CONCEPT Cited by 1 source

Schema-change deploy order

Definition

Schema-change deploy order is the operational rule governing which of the two deploy units (code or schema) must ship first for a given class of schema change so the production application never observes an inconsistent state. It is the expand-migrate- contract pattern reduced to a per-change-type instruction that a tool can emit to a developer at pull-request time.

The two canonical rules (Coutermarsh, 2024)

Mike Coutermarsh's 2024 PlanetScale post How PlanetScale makes schema changes names them verbatim:

  1. "When removing a column, application code must be deployed before the schema is changed"
  2. "When adding a column, application code must be deployed after the schema is changed"

Both rules have the same structure: the system that is reducing scope deploys second; the system expanding scope deploys first.

Remove-column: code first

If the schema drops the column first, application code still writing/reading the column throws errors until the code deploy catches up. The safe order:

  1. Deploy application code that stops referencing the column (both reads and writes).
  2. Verify nothing writes to the column anymore.
  3. Deploy the schema change that drops the column.

Add-column: schema first

If code deploys first and tries to write to a column that doesn't exist yet, writes fail. The safe order:

  1. Deploy the schema change that adds the column (nullable, or with a default).
  2. Deploy application code that reads/writes the new column.

Why this is the operational instruction altitude of

expand-migrate-contract

The full expand-migrate- contract pattern has six steps (Expand → Write both → Backfill → Read new → Stop writing old → Contract). That's the full pattern for structural changes — renames, type changes, splits, merges. For the common additive / subtractive cases, the pattern collapses to a two-step sequence — which of the two deploy units goes first?

Coutermarsh's two rules encode the collapsed form. A PR-bot using the PlanetScale API can detect the class-of-change (add_column vs remove_column) and emit the appropriate rule as a comment on the PR, without asking the developer to internalise the full six-step pattern.

(Source: sources/2026-04-21-planetscale-how-planetscale-makes-schema-changes.)

The deeper principle

The rules derive from the two-critical-systems-cannot-deploy-atomically invariant. The code and the schema are two independent deploy units. During the window between deploys, the production application runs against a version-mismatched schema. The question is which direction of mismatch is safe:

Change First deploy Window state Safe?
Add column Schema Schema has new col, code doesn't read/write ✓ — code just ignores new col
Add column Code Code writes to col that doesn't exist ✗ — writes fail
Drop column Schema Col gone, code still reads/writes ✗ — reads/writes fail
Drop column Code Code stopped using col, col still exists ✓ — col is just unused

Rule-of-thumb: deploy the unit that expands the contract first, then deploy the unit that reduces the contract. Expansion is backward-compatible; reduction isn't.

Structural changes: neither order is safe → use full expand-migrate-contract

For renames, type changes, splits, and merges, neither two-step order is safe because the change is both an expansion and a reduction at once. The safe procedure requires the full six-step expand-migrate- contract dance: add the new representation alongside the old, dual-write, backfill, cut reads over, stop writing the old, drop the old.

The deploy-order rule for structural changes is therefore many deploys, not two: the sequence itself is the instruction.

Encoding as PR-bot output

The PR-bot pattern in patterns/pr-bot-auto-deploy-request emits the deploy-order rule as a comment on the pull request:

"With our bot, we are able to use the PlanetScale API to detect the class of changes being made to the database. The bot then generates comments based on the characteristics of the changes, including instructions for the sequence of steps needed to make the change safely for our application." (Source: sources/2026-04-21-planetscale-how-planetscale-makes-schema-changes)

This shifts the cognitive burden from "every engineer remembers the expand-contract pattern for every change type" to "the bot reads the diff and tells the engineer which of code-first / schema-first / full- expand-contract applies."

Seen in

Last updated · 378 distilled / 1,213 read