Skip to content
Mobile6 min read

Shipping mobile: the release you cannot take back

Web deployment has a rollback button. Mobile does not: once a build is installed, it is on the device until the user updates, and some of them never will. That single constraint changes what a release process has to do — every mistake ships to people who cannot be reached.

Part ofMobile App Development

A bad web deploy affects users until you revert it, which is minutes. A bad mobile release affects everyone who installed it until they install something else, which is days for the attentive, months for most, and never for a meaningful minority. Every practice below exists because of that asymmetry.

Staged rollout, with something to watch

Both platforms can release to a percentage of users. Using it is the closest thing to a rollback that mobile offers, since halting a rollout prevents further installs even though it does not recall the ones already made.

  1. Internal testers first, on real devices, for at least a day of ordinary use.
  2. 1% of users, held long enough to gather crash data — hours, not minutes.
  3. Compare crash-free sessions against the previous version, not against an absolute threshold. A drop from 99.8% to 99.1% is severe and breaches no alarm.
  4. 10%, then 50%, then 100%, with a pause at each step and someone actually looking.
  5. Halt immediately on a regression. Halting is cheap; a full rollout of a crashing build is not reversible.

The old version runs forever

This is the fact most teams underestimate. A meaningful share of any installed base is running a build from a year ago — devices with automatic updates disabled, storage-constrained phones, users who dismiss prompts, and regions where data cost makes updating a decision.

  • Your API must keep working for versions you no longer support, or those users experience the app simply breaking
  • Never remove an API field a shipped version reads. Deprecate, measure by client version, and remove only when usage is genuinely zero
  • Version your API requests from the client, so the server can serve compatible responses rather than guessing
  • Instrument which app versions are in use, because the decision to drop support has to be based on real numbers
  • Assume every shipped version is live until the data says otherwise

The practical consequence is that mobile releases constrain backend design permanently. An API change that would be routine for a web application is a breaking change for an installed base you cannot update — which is why additive-only design matters more here than anywhere else.

Server-side switches, which are the real rollback

Since you cannot recall a build, the only way to change its behaviour after release is for the build to ask the server what to do. That has to be designed in before the release, not after the incident.

json
// Fetched at launch and periodically, cached locally with a sane
// default so a failed fetch never bricks the app.
{
  "features": {
    "new_checkout": false,        // disable a broken feature remotely
    "background_sync": true
  },
  "minimum_version": "2.1.0",     // below this, require an update
  "recommended_version": "2.4.0", // above this, suggest one
  "message": null                  // an in-app notice when needed
}

// Requirements that are easy to get wrong:
//  - a safe default if the fetch fails, so an outage in this
//    endpoint does not disable the app
//  - a cached last-known config, so offline launches still work
//  - this endpoint must be more available than everything else,
//    because it gates everything else

Forced upgrades, used sparingly and humanely

Blocking an old version until the user updates is occasionally necessary — a security defect, a data-corrupting bug, a backend contract that genuinely cannot be maintained. It is also user-hostile, so the bar should be high and the execution careful.

SituationResponse
Security vulnerability in the clientForce — this is what forcing is for
Bug corrupting user dataForce
Backend contract that cannot be maintainedForce, after trying hard not to
New features the user has not asked forRecommend, never force
Design refreshRecommend
Anything primarily benefiting your metricsNeither
  • Say why an update is required, specifically, rather than showing a blocking wall with a button
  • Link directly to the store listing, and handle the case where the update is not yet available in that region
  • Never force-block an offline device that could otherwise do useful work with local data
  • Give a soft-prompt period before a hard block, where the platform and severity allow it
  • Never discard unsynchronised local data as part of forcing an upgrade

Cadence, and what it costs

Release frequency is a trade-off specific to mobile, because each release carries review latency and a rollout period, and users bear the cost of updating.

CadenceSuitsCost
WeeklyLarge teams with strong automationReview overhead and rollout monitoring every week
FortnightlyMost product teamsA reasonable balance, and the common default
MonthlyStable products, small teamsLonger to fix anything not remotely switchable
On demand onlyInternal or tightly scoped toolsSkills atrophy; the release that matters is the risky one

Before each submission

  1. Version and build numbers incremented, and the build reproducible from a tagged commit.
  2. Crash reporting and symbol upload verified working in this build, not the previous one.
  3. Migration from the currently released version tested on a device holding real prior data.
  4. Tested on the oldest OS version you claim to support, and on a low-end device.
  5. Signing credentials valid and not near expiry, with someone other than one person able to release.
  6. Remote configuration fetched correctly, including its behaviour when the fetch fails.
  7. Release notes written for users, and an internal note of what to watch during rollout.

Item three is the one skipped most often and the one that produces the worst failures. Testing a fresh install proves nothing about an upgrade, and the upgrade path — with a populated local database written by the previous version — is what almost every user will actually take.

Questions

How do I roll back a mobile release?

You cannot. An installed build stays on the device until the user updates, so the closest equivalents are halting a staged rollout to stop further installs, and server-side switches that let a released build be told to disable a feature. Both must be in place before the release — a remote flag introduced in the same version as the feature it controls is useless if that version is the problem.

How long do I have to support old app versions?

Longer than expected. A meaningful share of any installed base runs a build from a year ago — automatic updates disabled, storage-constrained devices, users who dismiss prompts, regions where data cost makes updating a decision. Instrument which versions are actually in use and base the decision on that. In the meantime your API must keep working for them, which makes additive-only API design more important on mobile than anywhere else.

When is it acceptable to force an upgrade?

For a security vulnerability in the client, a bug corrupting user data, or a backend contract that genuinely cannot be maintained. Not for new features, a design refresh, or anything primarily benefiting your own metrics. When you do force it, say why specifically, handle regional availability of the update, never block an offline device that could still do useful work, and never discard unsynchronised local data in the process.

What gets missed most often before submission?

Testing the upgrade path. A fresh install proves nothing about what happens on a device holding a local database written by the previous version, and that is the path almost every real user takes. Close behind: verifying crash symbol upload works in this build rather than the last one, and checking signing credentials are valid and not held by one person.

Want this applied to your systems?

Most of what is described here begins as an assessment: a fixed-scope review producing a prioritised written report you can act on with any supplier.

Prefer email? hello@kornspire.com