Skip to content

Launch6 min read

Forced updates and minimum versions: why the check must ship in version one

By Published

Short answerA forced update only works on copies of the app that already contain the check, so it has to ship in version one. Store the minimum supported version somewhere you control, such as Firebase Remote Config or your own backend, compare it with the installed version at launch, and block or prompt. On Android, Google Play's immediate in-app update can then install the update. Apple offers no equivalent, so on iOS you send users to the App Store.

An installed app only obeys the code it shipped with

Version one is the only version you can count on everyone having had. Some users will keep it for a long time.

Apple's support page says apps update automatically by default, and it also shows users how to turn that off. Google Play describes its in-app update prompt as a reminder for users who do not update in the background. Either way, some phones will still be running your first build months after you have moved on.

Now picture the day you need them to move. Your booking API changes shape. A payment step has a bug that charges twice. A security fix cannot wait. If version one has no minimum version check, you cannot tell those phones anything. You can keep the old API alive indefinitely, or let the old app break in front of customers. I would not ship a first version that talks to a backend without this check. It is a few hours of work at the start and impossible to add backwards.

What Google Play and Apple give you

Google Play has a built-in answer. Its in-app updates feature, part of the Play Core libraries, offers two flows. A flexible update downloads in the background while the user carries on, and your app asks them to restart when it is ready. An immediate update is a full-screen flow that requires the user to update and restart before they can continue, and Google says it suits updates that are critical to the core functionality of the app.

There are conditions. It needs Android 5.0 (API level 21) or higher, works on phones, tablets and ChromeOS, and only reaches accounts that own the app through Google Play. You can attach a priority from 0 to 5 to each release, but only through the Google Play Developer API, only when you roll the release out, and it cannot be changed later. The user can still cancel an immediate update. Google's guidance for an app that cannot run without the update is to show a message and restart the flow, or ask the user to close the app.

Apple is different. The release options in App Store Connect are manual release, automatic release after approval, and automatic release no earlier than a date you set. Phased release spreads an update over 7 days to users with automatic updates on, and Apple notes anyone can update manually at any time. None of the Apple pages I checked describes a setting that makes an installed copy update. On iOS the check, the blocking screen and the link to your App Store page are all yours to build.

A worked version check, from launch to a breaking change

Here is the flow I would build for a Flutter booking app using Firebase Remote Config. Remote Config keeps default values inside the app and lets you override them from the console, which is exactly what a version gate needs.

Version 1.0.0 ships with three parameters and in-app defaults: min_supported_version set to 1.0.0, latest_version set to 1.0.0, and update_message with a short, friendly line. At launch the app fetches and activates the config, reads its own version, and compares the numbers.

Months later, version 1.3.0 moves bookings to a new API endpoint. The order of operations matters:

  • Release 1.3.0 on both stores. Keep the old endpoint running.
  • Wait until 1.3.0 is visible on both stores. Apple says a manually released version can take up to 24 hours to appear; a staged Play rollout needs to reach 100%.
  • Set latest_version to 1.3.0. Users on 1.0.0 to 1.2.x now see a dismissible "update available" banner. On Android this can be a flexible update.
  • A week or two later, set min_supported_version to 1.3.0. Older copies now show a full-screen "please update" page with one button to the store. On Android, start an immediate update instead.
  • Watch the share of sessions still on old versions. When it is low enough for you, retire the old endpoint.

What each user sees on the day the minimum moves

With min_supported_version at 1.3.0 and latest_version at 1.3.0, the gate behaves like this:

Installed versionCompared with the configWhat the app does
1.0.0Below the minimumBlocks with the update page. Android starts an immediate update.
1.2.4Below the minimumSame block. 1.2.4 is still lower than 1.3.0.
1.3.0Equal to minimum and latestOpens normally.
1.10.0Above bothOpens normally. A plain text comparison would wrongly put "1.10.0" below "1.3.0", so compare each number in turn.
Any version, offlineConfig cannot be fetchedUses the last activated values or the in-app defaults. Never block just because the fetch failed.

Mistakes that lock out the wrong users

Each of these I would test before release, because each one fails on real customers rather than on the test phone.

  • Raising the minimum before the new version is live on both stores. Users hit a wall with nothing to update to.
  • Forgetting the fetch interval. Remote Config's default minimum fetch interval is 12 hours, so a change can take that long to reach a phone. Real-time Remote Config, available from the Flutter SDK v4.0.0, can deliver it sooner.
  • Relying on the app alone. I would also send the app version with every API request and have the backend refuse unsupported versions with an error the app recognises, so an outdated copy fails politely instead of corrupting data.
  • Putting anything secret in Remote Config. Firebase warns that users can read every parameter available to their app instance.
  • Using the gate for small changes. Google asks developers to request in-app updates only for changes that matter to core functionality, and I would hold the iOS gate to the same standard.

Where this sits next to maintenance and target API work

This check is a feature of the app. A maintenance contract decides who changes the minimum and how quickly, and the yearly Google Play target API upgrade is often the release that needs a minimum raised. Both have their own posts, linked below.

In my packages, Launch ($999) connects to the APIs you need, so the gate would read from Remote Config. Growth ($1,699) includes your own Node.js backend, where the minimum version can live next to the API it protects. Scale ($2,500) adds an admin dashboard scoped to your operations, and the minimum version field can go there if you want to change it yourself. I recommend putting the check in the written scope of version one. Ongoing maintenance, including raising the minimum later, is not included in the package prices.

Questions

Can Apple force users to update my app?
Not through any setting I found in Apple's App Store Connect documentation. Apps update automatically by default, but users can turn that off. Your app has to check its own version and send the user to the App Store.
Can I add a forced update check in version two instead?
You can, but it only protects copies that have version two or later. Anyone still on version one will never see the check, so a breaking backend change can still reach them.

Sources

Platform rules and fees in this article were checked against these official pages on 10 November 2026. They change, so confirm before you rely on them.

Sannan Malik is a software architect and product builder with 8+ years in software, CEO of Alpha Notic FZC and a Certified Scrum Product Owner. He builds mobile apps and business software for companies in the UAE, UK and US.

Let's build it

Got an idea? Let's talk.

The fastest way to reach me is WhatsApp. Tell me what you're building and I'll reply with how I'd approach it, which package fits, or what a custom scope would look like.

Message me on WhatsApp