Skip to content

PATTERN Cited by 1 source

Migration script travels with application code

Pattern

The schema migration script for a feature lives in the same git repository, the same git branch, and the same pull request as the application code that depends on it. There is no separate ticket, no separate review, no separate deploy queue, no separate repo for schema changes. "Schema and data migration travels with code."

The migration tool format is platform-orthogonal — Flyway, Liquibase, Alembic, Knex, Prisma all produce migration files that fit the pattern. What's load-bearing is the same-repo + same-PR + same-review principle, not the specific tool.

Canonical statement

"Jen writes the migration script. Whatever her team uses – Flyway, Liquibase, Alembic, Knex, Prisma – the script lives in the code repo, alongside the application changes. Schema and data migration travels with code."

"Jen commits both the application code and the migration script. She opens a PR."

(Source: sources/2026-05-29-databricks-enabling-evolutionary-database-development-database-branching-with-lakebase)

What the pattern dissolves

Pre-pattern, schema changes lived in separate workflows:

Application change Schema change (pre-pattern)
Lives in app git repo Sometimes a separate "schema repo"
Reviewed by app team Reviewed by DBA via ticket queue
Tested in CI Often only tested at deploy time
Deployed via app pipeline Deployed via DBA-operated migration window
Released atomically with code Released before code (additive-only) or after code (rollback considerations)
Visible in PR diff Sometimes invisible to PR reviewer

The decoupling produced specific failure modes:

  • PR reviewers couldn't reason about the change holistically — schema half lives elsewhere, code half lives in the PR; the review is split.
  • Atomic rollback impossible — rolling back the application code didn't roll back the schema, and vice versa.
  • Out-of-order deploys — schema landed before code (additive) or after code (release-coordination tax).
  • Schema review queue became a bottleneck — see concepts/database-development-compensating-layer.

Post-pattern:

Application change Schema change (post-pattern)
Lives in app git repo Same git repo, same directory tree
Reviewed by app team + (optionally) DBA Reviewed in the same PR
Tested in CI Tested in CI against an ephemeral branch
Deployed via app pipeline Deployed via the same pipeline
Released atomically with code Released atomically with code by construction
Visible in PR diff Visible alongside the code that uses the new columns

Why this matters under evolutionary database design

Evolutionary database design (Fowler 2003, Sadalage 2006) explicitly requires Practice #7 — version-control everything, including the schema. The methodology says schema changes are first-class code artefacts. But the pre-pattern industry split the workflow because of two missing capabilities:

  1. No per-pipeline isolation ( Practice #4 aspirational) — without isolated test environments, pre-merge migration validation was impossible, so DBAs validated by hand at deploy time.
  2. No CI-side validation — without copy-on-write branches, CI couldn't run migrations against production-shaped data, so the breakage class went to the DBA.

Both gaps closed in 2026 with copy-on-write branching. The pattern becomes operational because:

Relationship to Continuous Delivery (Humble & Farley 2010)

The pattern's intellectual lineage:

  • Fowler 2003Evolutionary Database Design essay articulates Practice #7 (version-control everything, schema included).
  • Sadalage 2006Refactoring Databases operationalises the practice with a refactoring catalog + transition mechanics.
  • Humble & Farley 2010Continuous Delivery Chapter 12 ("Managing Data") brings migration scripts into the deployment pipeline as first-class artefacts. This is when schema-as- code reached the CI/CD movement.
  • 2026 — copy-on-write branching closes the per-pipeline- isolation gap that Continuous Delivery couldn't solve in 2010.

The Databricks 2026-05-29 post canonicalises the gap explicitly:

"That methodology reached CI/CD in 2010 with Continuous Delivery (Chapter 12: Managing Data). Migrations became first-class artifacts in the deployment pipeline. The discipline of database-changes-as-code reached the broader CI/CD movement. What CD didn't solve was per-pipeline isolation: pipelines could run migrations, but they still needed a target database, and that target was shared."

(Source: same)

Migration tool list (platform-agnostic)

The pattern is tool-orthogonal — any of the following works:

Tool Language Migration format
Flyway Java (multi-DB) SQL files, sequentially numbered, optional undo files
Liquibase Java (multi-DB) XML / YAML / JSON / SQL changesets
Alembic Python (SQLAlchemy) Python scripts with upgrade() / downgrade()
Knex Node.js JS files with exports.up / exports.down
Prisma Node.js / TypeScript Generated SQL files from schema diff

The post explicitly lists all five as equivalent for the pattern's purposes. The substrate (Lakebase / Neon / PlanetScale) doesn't dictate the migration-tool choice — the migration tool operates against the branch's connection string, blind to the storage layer underneath.

Trade-offs

Upsides

  • Holistic PR review — reviewer sees code + schema together; catches mismatches at review time.
  • Atomic deploy + atomic rollback — schema change ships with the code; rollback rolls both back together.
  • Single review queue — no separate DBA ticket queue blocking schema changes.
  • Migration is tested with the app — not validated separately and hoped to compose at deploy time.
  • Refactoring catalog becomes routine — the cost of moving a schema change into the same PR drops to zero.

Downsides

  • Backward-compatibility considerations during multi-step rollouts — code that requires the new schema can't ship before the migration applies. Solved by expand / contract migrations (additive change in one PR, code that depends on it in a later PR after the additive change is live).
  • Long-running migrations don't fit one PR cycle — a multi-hour data migration can't gate a PR. Solved by expand-only-at-PR-time + background-data-migration-after- merge shape.
  • DBA review still needed for design questions — the pattern doesn't replace the DBA; it just removes the gating cost. See concepts/dba-as-design-collaborator.
  • Cross-team schema changes that affect multiple application repos still need coordination at a higher altitude.

Relationship to adjacent patterns

Seen in

  • sources/2026-05-29-databricks-enabling-evolutionary-database-development-database-branching-with-lakebaseFirst canonical wiki instance of the same-PR migration pattern. Databricks 2026-05-29 Tier-3 post. Lists the five-tool platform-agnostic migration tools (Flyway, Liquibase, Alembic, Knex, Prisma), names the "schema and data migration travels with code" principle, and describes Jen's PR opening with both halves of the change in one commit. Frames the lineage from Fowler 2003 → Sadalage 2006 → Humble & Farley 2010 (Continuous Delivery, Chapter 12) → 2026 substrate change.
Last updated · 542 distilled / 1,571 read