Building Apps with AILesson 83 of 87

Contents

Building Apps with AI

Lesson 83 of 87. Sign in to keep your place.

Module 9 · What it costs, running it, and where this stops

Shipping changes without breaking what works

8 min read

Renaming a column without a minute of errorsRelease 1Expand. Add phone_number. Code writes both columns and reads the new one, fallingback to the old.BetweenA backfill copies every old value across. Nothing has been removed, so the rollbackbutton is still safe.Release 2Switch. Every row has the new column and no old code is running; the code now usesonly phone_number.Release 3Contract. Drop phone, in its own later migration.A migration and a deploy are two events with a gap between them, and during the gap one version of thecode runs against the other version of the schema. Each release here works on both sides of its owngap.
A migration and a deploy are two events with a gap between them, and during the gap one version of the code runs against the other version of the schema. Each release here works on both sides of its own gap.

Figure

The routine

The shipping block gave you the pieces: branches, previews, the version stamp, the rollback button. This lesson puts them in order, because the order is what keeps a release from being a gamble.

  1. Branch. Build the change with the agent, commit at each checkable step.
  2. Push. Open the pull request, read the diff as a whole, run the checks: build, typecheck, the three-account script, the eval set if the AI feature changed.
  3. Preview. Open the preview URL on your phone. Run the two-minute check on the changed feature and the stranger’s checklist on the main path.
  4. Migrate, additively. If the schema changes, the migration adds; it never renames or drops in the same release as the code that stops using the old shape.
  5. Merge. The host deploys. Confirm the version stamp on the live site matches the commit.
  6. Watch. Fifteen minutes with the error tracker open and the daily-count query handy. Then walk away.

Steps 4 and 6 are the ones people skip, and they are the ones that turn a small mistake into a visible outage.

Expand, then contract

The question above is the classic. A migration and a deploy are two events with a gap between them, and during the gap one version of the code runs against the other version of the schema. A rename breaks whichever version is on the wrong side.

The pattern that survives has three releases:

Expand. Add phone_number. Deploy code that writes both columns and reads the new one, falling back to the old. A backfill copies old values across.

Switch. Once every row has the new column and no old code is running anywhere, deploy code that only uses the new column.

Contract. A later release drops phone.

Three small releases, each of which works with the schema on both sides of its own gap, and any of which can be rolled back with the button. It feels slower and it is the only way that never produces the minute of errors. Put the rule in the rules file: migrations add; removals go in a separate, later migration.

A flag for anything you might turn off

A new feature that turns out to be broken at 9pm should be switchable off without a deploy. The simplest flag is an environment variable read at request time (FEATURE_AI_SUMMARY=off) and a check in the route. The next step is a flags table with a name, an on-off value, and optionally a list of user ids or a percentage, so that a feature can go to you first, then ten percent, then everyone.

A flag is not a permanent branch in the code. Once the feature has been on for everyone for a few weeks, remove the flag and the old path. Flags that live forever are the dead code the reading block warned about, with a switch attached.

Deciding the rollback before you need it

Before merging, answer one question: what would make me press the rollback button? A new error type from the changed route, the daily count dropping, a report from the button. Write it in the pull request. Then when it happens at minute eight of the fifteen, the decision is already made and the button takes three seconds. The rollback lesson said the database does not roll back with the code; the expand-then-contract rule above is what makes the button safe to press.

When to ship

Not at the end of the day, and not before a weekend, for a plain reason: the fifteen minutes of watching need a person, and the report that arrives at 11pm needs one too. Ship when you have an hour after it to be available. A release on Tuesday morning that breaks is a Tuesday morning problem; the same release on Friday evening is a weekend.

Telling users

A line in the app, or a changelog page, or an email for the big ones: what changed, in their words rather than yours. “You can now cancel a booking from the confirmation email” rather than “Added cancellation endpoint”. Users who know what changed report problems accurately, and a public changelog is the record you will search when a complaint says “since last week”.

The whole routine takes an hour

Most of it is waiting for builds and reading. It replaces the alternative, which is merging to main at midnight, deploying, and finding out in the morning. The routine is the difference between an app that a stranger can rely on and one whose users have learned to try again tomorrow.

Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.

Check your understanding

A release renames the column phone to phone_number in one migration and deploys code that reads phone_number. Users report errors for about a minute after the deploy. Why, and what would have prevented it?

Pick the one you would defend. Your answer stays private.

Next lesson · 8 minHanding it to a real developer

Stuck on something?Ask Beatriz, your AI tutor

How to cite: Addaly (2026) ‘Shipping changes without breaking what works’, in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/shipping-changes-without-breaking-what-works (Accessed: 13 October 2026).