By Chason ArthurRevision 142.069Published Updated

Delivery / Database migrations / Infrastructure as code

Ship the change. Keep the customers.

A new application wants a renamed field. The old application still reads the original. Release both through a compatibility window and find out whether rollback can actually work.

The idea in plain language

During a release, old and new application versions may share one database. A compatible migration lets both work until the old readers and writers have been retired.

Actual PostgreSQL executes the migration and client reads. Traffic and readiness phases are an explicit browser model. The download includes a real loopback HTTP switch and a local-only Terraform plan exercise; no cloud deployment is started from this page.

Your independent testing environment

Make the failure visible.

Run the column-rename example. Watch an old client fail after a destructive change. Then compare expansion, backfill and dual writing. The other presets test a failed canary and an early attempt to remove the old column.

Compare a destructive rename with expansion, backfill and compatible reads.

Ready. Choose an example and run both implementations.

Explain the result

All safeguarded data reads return 200 across mixed versions and application rollback. The destructive path produces missing-column errors. The contract gate refuses to remove a column while an old reader remains.

Open the exact source behind this edition. The viewer checks each file against its SHA-256 manifest and explains the decision it implements.

Download this lab

Choose your next step

Build the safeguards

Eight explained steps, a source example and a checkpoint at each decision.

Read the tutorial

Compare the alternatives

Understand where each pattern helps and which tradeoffs remain.

Compare approaches

Run and extend it locally

Download the independent environment, run the native checks and try a specific extension.

Open the how-to guide

Before you try it

Do I need to know how to code?

Start with Run and read the comparison. The tutorial introduces the code after you have seen the behavior. The how-to guide separates a no-install route from the native developer exercise.

What happens to the experiment when I reset?

Reset discards this lab’s temporary state and cancels or terminates its pending work. These examples use invented records. No account, production data or cloud deployment is needed.

What does the browser experiment establish?

Actual PostgreSQL executes the migration and client reads. Traffic and readiness phases are an explicit browser model. The download includes a real loopback HTTP switch and a local-only Terraform plan exercise; no cloud deployment is started from this page.

Lab discussion / Safe Rollout Lab

What would you try next?

Ask about the code, compare an approach, or describe an edge case. Reader comments are reviewed before publication.

All lab discussions

Reader comments

Open the discussion to read and add reader comments.

Read or write a comment →

Code walkthrough

Follow the implementation in code.

These short excerpts connect the lab’s behavior to its implementation. Each example links to the full tutorial step for its context, tradeoffs and checkpoint. Names and dependencies belong to that source; the excerpts are not standalone programs.

Example 01 · Tutorial excerpt

Expand without removing the old contract

Add the new field while keeping the old one. This gives new code somewhere to read without breaking existing consumers. The right production DDL strategy also depends on locking, table size, defaults and the database version; this tiny table demonstrates compatibility only.

ALTER TABLE profiles ADD COLUMN display_name text;

Read the full tutorial step

Example 02 · Tutorial excerpt

Backfill and keep writes compatible

Copy existing values, then maintain both representations during the transition. A one-time backfill is insufficient if an old writer continues changing only the old field. This exercise’s compatible writer sets both fields; the extension challenge deliberately introduces an old writer.

UPDATE profiles SET display_name=full_name;
UPDATE profiles SET full_name=$1,display_name=$1 WHERE id=$2;

Read the full tutorial step

Example 03 · Tutorial excerpt

Gate traffic on meaningful readiness

The readiness preset marks the canary unready. The browser models the traffic decision, while its data reads remain real. A production readiness probe must reflect the dependencies required to serve safely; a process merely listening on a port may not be sufficient.

if (!canaryReady) keepTrafficOnVersionOne();

Read the full tutorial step

Example 04 · Tutorial excerpt

Rehearse application rollback

The local exercise starts a real loopback HTTP service, switches its query to version two, then switches back after an injected readiness failure. It retains the expanded schema. Reverting an application does not automatically undo a migration or restore removed data.

activeVersion = 1; // retain the expanded schema

Read the full tutorial step

Example 05 · Tutorial excerpt

Keep contraction behind a separate gate

The old field may be removed only after old readers and writers are gone and backfill is complete. The gate explicitly checks all three. Production evidence may come from deployment inventory, job configuration and observability; the browser’s consumer count is a reviewed fixture.

oldReaders === 0 && oldWriters === 0 && backfillRemaining === 0

Read the full tutorial step