Skip to content

From the team

Shipping mobile releases without drama

App review is not the risky part. Not being able to turn a feature off is.

4 min read

The web lets you fix a mistake in minutes. Mobile does not: a bad build can sit in front of users for days while a review queue moves. That single difference should shape how you release.

Decouple release from launch

Ship the code dark behind a flag, then turn the feature on from the server once it is in enough hands. Now "roll back" is a config change rather than an emergency submission, and a feature that misbehaves at 2am can be switched off by whoever is awake.

Stage the rollout

Both stores support phased releases. Use them. One percent for a day catches the crash that only happens on a three-year-old Android device with a locale you did not test.

Watch the right number

Crash-free sessions is the headline metric, but it hides slow failures. Track the completion rate of your one critical flow — signup, checkout, booking — per app version. A release that does not crash but drops checkout completion by eight points is a worse release than one that crashes.

Make the client's build reproducible

Signing keys in one person's keychain is the most common way a project becomes unmaintainable. Keys in the client's own secret store, CI that can produce a release build from a clean checkout, and a documented procedure someone else has followed at least once.

Build the force-update switch before you need it

Sooner or later a version has to be retired: a security fix, a breaking API change, a bug that corrupts data. If the app has no way to refuse to run, your only option is to keep the old client working forever — which means the API can never change.

So the app asks the server, on launch, whether its version is still supported, and the server answers with a minimum version and a message. It costs an afternoon to build while everything is calm, and it is unbuildable at the moment you actually want it.

Version your API from the first release

A web client updates when the server does. A mobile client does not — people run last year's build, and some of them will never update. From the first release onward, every version you have ever shipped is a client you are still supporting.

That makes API versioning not a nicety but the thing that lets you change anything at all. Additive changes only within a version, a new version for anything breaking, and a deprecation window measured against how quickly your users actually upgrade rather than how quickly you'd like.

Budget for the annual churn

Both platforms ship a major OS version every year, deprecate APIs, raise the minimum SDK you can submit against, and change store requirements — privacy disclosures, permission justifications, tracking declarations. None of it is optional and none of it delivers a feature, which is why it never makes it into a roadmap.

An app left untouched for two years typically needs weeks of work before it can be submitted at all. Planning a small maintenance allocation each year is cheaper than the rescue project, and it is a much easier conversation to have in advance than during a release freeze.

Test in both directions before you submit

For a bilingual app, half the release surface is the half you are not reading. Switch the device language to Arabic and walk the critical flow: the layout mirrors, the back gesture goes the right way, dates and numerals format correctly, and nothing is truncated by text that sets longer than the English.

This is worth a checklist rather than good intentions, because it is always the thing nobody looked at, and a store review cycle is an expensive way to discover a clipped button.