New Features, Old Phones, and a Banner We Control From the Server
DanDan·2 July 2026·6 min read

New Features, Old Phones, and a Banner We Control From the Server

TL;DR

Most people will not read to the bottom, so here is the whole thing in one line: control your app's update prompts from the server, not from the app. Ship a simple banner that shows whatever message the server hands it, and let the server decide which versions see it. You cannot add this to a version already sitting on someone's phone, so build the empty slot in now, before you need it. Everything below is how we got there, and where the AI tripped over itself on the way.

This is the latest in my running series on what building a small business with AI in the loop is actually like. Earlier ones covered the time it nearly published our subscriber list, the day it emailed the wrong Dan, and what our golf app taught us about putting AI into a real product. This one is about a problem every app hits eventually: what do you do about the people who never update?

What I set out to do

We shipped a big release of our golf app. Guests who can play a tournament without an account, joining a game by code, one person scoring a whole group. Good stuff, and the sort of thing people actually asked for.

The catch is that all of it needed changes to the database, and the moment those changes go live, every copy of the app already out there is talking to the new database. Including the old versions that know nothing about the new features. A phone running a version from a month ago does not magically learn about guests. It just meets data it was never built to understand, and falls over.

So the real question was never "how do we build the features." It was "what happens to someone on an old version when they walk into one of these new tournaments, and how do we get them to update."

What the AI nailed

Once we had actually settled on an approach, the build was quick. Claude wrote the version check, the banner, the translations into all six languages we support, and a set of tests, in about the time it takes to make a coffee.

The reasoning was good too. When I asked whether we should just force everyone to update, it talked me out of it for the right reason. A forced update is one bad line of logic away from locking every user out of the app with no way back except shipping another release, which you cannot do quickly. Dismissible was safer. It made that call clearly and I agreed with it.

Where it went wrong (this is the point)

Several things, and they rhyme with the rest of this series.

First, it did not raise the old-version problem at all until I did. I had to be the one to ask, "what about people who have not updated?" When I did, it produced a genuinely sharp analysis. Then it opened that analysis by telling me what an excellent question it was. I had to point out that praising my question is not the same as having thought of it first. The tool is happy to be brilliant on demand and strangely reluctant to volunteer the awkward thing before you poke it.

Second, it kept trying to build before we had decided what to build. I would ask a design question and it would start writing files. I stopped it more than once to say we are still talking, not coding yet.

Third, and this is the properly useful one, its first instinct was to check the wrong number. Every app has two versions: the friendly one you set by hand, like 4.13.0, and a build number that the build system bumps automatically every time, which you do not even know in advance. It reached for the automatic one, which would have been a nightmare to keep in sync. I steered it to the version we actually set by hand. That one change turned a fragile idea into a simple one.

Fourth, the first banner was rubbish. It jammed it inline into the home screen and made the update link a tiny bit of text you had to aim at with your thumb. I asked for a proper floating banner with a real button. It fixed it fast, but left to its own taste the first pass was not something I would put in front of a user.

Fifth, it nearly shipped the blunt version of the idea: if you are not on the very latest release, nag you. I had to point out that most updates do not break anything, so nagging everyone on every release is just noise. The nudge should only show up when the version genuinely cannot handle what it is about to load.

What we landed on: a message we control from the server

The approach we settled on is almost dumb, and that is exactly why I like it.

The app does not decide anything clever. On startup it reads its own version, asks our server "is there a message I should show, and which versions should see it," and if it qualifies, it shows a small banner the user can dismiss. The wording lives on the server, not baked into the app. So we can change the text, point it at a different version, or switch it off entirely, all without shipping a new release. Dismiss it once and it stays gone until we publish a genuinely new message.

The honest limitation is the interesting part. This only helps people whose app already has the banner code inside it. You cannot add a check to a version that is already sitting on someone's phone. So the thing we just shipped does nothing for today's stragglers. What it does is quietly future-proof us, so the next time we make a breaking change, everyone on this version or later gets a clean, well worded nudge, in their own language, that we can write on the day. You fit the letterbox now so you can post through it later.

For the people already on old versions, the answer is less magic and more legwork: an email to everyone, a note in the in-app news feed, and, next on my list, a proper software update button inside the app so updating is one tap instead of a hunt through the store.

What I would tell you

  • You cannot retrofit old apps. Whatever check you want future-you to lean on, it has to ship now. Fit the empty slot early, before you need it.
  • Compare the version you set by hand, never the build number. The automatic one is not knowable in advance and will fight you the whole way.
  • Only nudge when it genuinely breaks, not on every release. "You are not on the latest" is noise. "This will not work properly on your version" is a reason.
  • Do not let the AI build before the design is settled. It is keen. Keen is not the same as ready, and undoing an eager half-build costs more than the pause would have.
  • The clever part is often the dumb part. A server that hands the app a message, and an app that simply shows it, beats any amount of on-device cleverness you would have to reship every time you wanted to change your mind.

None of this is unique to golf, or to us. Any app with users on more than one version has the same quiet problem, and most teams only notice it the day an old build meets new data. If you are building something with an audience you cannot force to update, and you want someone who has done this for twenty years to help you get the plumbing right, get in touch. The quote generator is the quickest way to see how we work, and the work page shows what we have built.

Not sure what you need yet? Start here.

No email requiredNo sales call neededGet a ballpark estimate in minutes
New Features, Old Phones, and a Banner We Control From the Server | All Trouser Digital