Programming with AI
ENRU
12.3

Shipping and updates

why the old version lives longer than you think

What it is

Shipping isn't the finish line but the start of a condition in which your program exists in several versions at once. The server updated, the applications on people's phones didn't. The website updated, the browser is holding the old file. The new version is in the store and half the people are on last year's.

So the main question with every update isn't "how do I put it out" but "what happens to the people still on the old one". Neither an AI nor the publishing tools ask that question — only you do.

What it looks like in code

Three ways of shipping, three different speeds

What we shipHow it reaches peopleCan it be rolled back
a websiteinstantly, at the next openingyes, instantly
a server, an APIinstantly, for everyone at onceyes, if prepared for
an app in a storeafter review, when people choose tono

The difference in the last column is the important one. A website rolls back in a minute. An application in a store cannot be rolled back: you can only release the next version and wait for people to install it. That is why mobile builds are checked more carefully and rolled out to a fraction of users rather than everyone at once.

A website: the cache, and how the build gets round it

Build the project twice in a row without changing a line:

$ npx vite build
dist/assets/index-CxiKQytF.js  222.62 kB │ gzip: 69.34 kB
$ npx vite build
dist/assets/index-CxiKQytF.js  222.62 kB │ gzip: 69.34 kB

The file name is the same. Now change one word in the text and build again:

$ npx vite build
dist/assets/index-Cfu8g7G7.js  222.62 kB │ gzip: 69.34 kB

The name changed. Those letters in the name are a fingerprint of the contents: different contents, different name. That is done for exactly one purpose: so that a browser holding files of its own doesn't hand the user old code. The old file in the cache bothers nobody — nobody will ever come for it again.

But one file in this scheme doesn't change its name:

measured
dist/index.html                  0.20 kB
dist/assets/index-Cfu8g7G7.js  222.62 kB

index.html is the file that says which of the hashed files to load. It must not be cached. If the hosting caches index.html for a day, the user will open the old page for a day, pointing at the old code, and no amount of publishing will fix it.

Hence the hosting rule worth knowing by heart: files with a hash in the name — cache for a long time; index.html — don't cache. It is the one setting worth checking by hand the first time you publish a site.

A server: the update hits people you weren't thinking about

A server updates instantly and for everyone. And here is where the thing nobody thinks about surfaces: old applications on phones have no "update now" button.

Rename a field in the API response and applications released six months ago stop showing the weather. Make a field required in a request and old versions stop sending data. Formally you changed your server; in reality you broke programs that are already on people's devices.

The rule that follows:

  • adding fields is fine, old clients simply won't notice them;
  • removing and renaming is not, as long as anyone using them is still out there;
  • if the change is unavoidable, a /api/v2/ appears alongside while /api/v1/ keeps working (article 7.3).

The second thing that breaks on a server is the database. Updating the database and updating the code don't happen at the same moment, and the order matters: first the new field is added, then the code that uses it is deployed. The other way round gives you a few minutes in which the code looks for something that isn't there yet.

And third: rolling back code is one command, rolling back a database change is not. A deleted column doesn't come back with the rollback. So database changes that delete something are deployed separately and later, once it is clear the new version is alive.

The store: what happens after the upload

measured
uploaded  →  review  →  available to some people  →  available to everyone

Review takes from hours to days and can end in rejection. The most frequent reasons for rejection aren't technical: permissions without an explanation (article 12.2), a demo that doesn't work for the reviewer, no privacy policy when the application collects anything at all.

A staged rollout — giving the new version to a small share of users first — is the only defence against the fact that a release can't be rolled back. If crashes start pouring in during the first day, the rollout is stopped and most people simply stay on the old, working version.

What to tell the AI

Shipping is the area where what is most useful from an AI is lists of checks, not actions.

Prompt
I'm changing an API response: the "temp" field becomes
"temperature". My mobile apps in the store don't update
immediately. What breaks for people on the old version?
Propose a way to make this change without breaking them.
Prompt
I'm adding a required field to the database. Write the order
of operations: what to deploy first, what second, and what
happens if they're deployed the other way round.
Separately: which part of this can't be rolled back.

That second request is worth asking every time the database changes. The answer to "what can't be rolled back" is precisely the list of things to do carefully.

Prompt
Here are my hosting's caching settings: <settings>.
The build files have a hash in the name, index.html doesn't.
What's configured wrongly and what will it lead to?
Prompt
Draw up a shipping checklist for my project: <description>.
Split it into "before shipping", "right after" and "a day
later". Only what applies to my stack.

What to look for

An API change with no thought for old clients. A field renamed, no version added. It works for you and is broken for everyone who hasn't updated.

A deletion in the database deployed together with the code. The rollback becomes impossible at exactly the moment you need it.

index.html is cached. Deploys stop reaching users, and the cause is hunted in the code.

No way to find out what broke. After shipping you need logs and error reports, or users will report the breakage — or won't.

Shipping done by hand and from memory. While it's five terminal commands you remember, one day you will run them in a different order.

The version isn't visible in the application. When a user complains, the first question is which version they have. If there is nowhere to look, the conversation doesn't happen.

A migration not tested on a copy of the data. Running a structure change straight against the real database is the most expensive possible way to find out it has a bug.

Cheat sheet

  • After shipping there are always several versions: think about the people on the old one.

  • A website rolls back instantly, a server if you prepared, an app never.

  • A hash in the file name is cache protection; index.html must not be cached.

  • "The browser has the old one" — check a private window before searching the code.

  • In an API you can add; you can't remove or rename.

  • The database field first, then the code; deletions separately and later.

  • Code has a rollback, the database doesn't.

  • Roll out to a fraction of users, and don't ship on a Friday.