You ship a redesigned home screen in a Flutter pharmacy app to Google Play and the App Store; why stage the release, and what can halting the rollout not undo?
answer
- Dart is AOT-compiled into the binary
- every fix goes back through review
- halting stops new users only
- no downgrade: ship a higher build number
- runtime switch between old and new screen
basics
~20 sRelease Dart is AOT-compiled into the binary, so every fix is a new reviewed build; staging limits who meets a bad one. A halt cannot downgrade users who updated: recover with a higher build number or a runtime switch.
solid answer
~50 sIn release mode a Flutter app's Dart code is AOT-compiled into native code inside the AAB or IPA, so a broken home screen cannot be patched from the server; the fix is a new binary that goes through store review. A staged rollout on Play, or phased release for automatic updates on the App Store, exposes the redesign to a small share of pharmacy users while you watch crash-free rates and prescription-refill completion. The trap is what a halt does: it stops new users getting the build, but users who already updated keep it, and stores do not downgrade. Recovery means shipping a new build with a **higher** build number, even if it contains the old code. The stronger design compiles both home screens into the binary and chooses one at runtime from a remote flag, so reverting needs no review at all.
code
dart · 27 linesimport 'package:flutter/material.dart';
class ClassicHome extends StatelessWidget {
const ClassicHome({super.key});
@override
Widget build(BuildContext context) =>
const Scaffold(body: Center(child: Text('Refill a prescription')));
}
class RedesignedHome extends StatelessWidget {
const RedesignedHome({super.key});
@override
Widget build(BuildContext context) =>
const Scaffold(body: Center(child: Text('Your refills are ready')));
}
class HomeGate extends StatelessWidget {
const HomeGate({super.key, required this.useRedesign});
final bool useRedesign;
@override
Widget build(BuildContext context) =>
useRedesign ? const RedesignedHome() : const ClassicHome();
}go deeper
Recall that a released Flutter app contains compiled Dart, so every fix is a new build through review.
Explain how Play's staged rollout and the App Store's phased release differ, and why a fix needs a higher build number.
Show a release plan that stages the binary, gates the redesign behind a runtime flag and watches crash and business metrics by build number.
Weigh how far to invest in runtime switches and staged exposure against release cadence, review latency and the risk of the flow in question.
## Why Flutter releases need staging In **release mode**, a Flutter app's Dart code, framework and application alike, is **ahead-of-time (AOT) compiled** into native machine code and packaged into the Android App Bundle or the iOS `.ipa`. Nothing in that binary downloads new Dart code at runtime. Two consequences: - A bug in the redesigned home screen is fixed only by **building a new binary** and getting it through review again, which takes hours to days. - Every user who installed the broken build keeps it until they install the next one. For a pharmacy app, where the home screen is the path to refilling a prescription, that window matters. A **staged rollout** limits how many users are in it. ## What each store gives you | | Google Play | App Store | |---|---|---| | Mechanism | staged rollout of a production release to a percentage of users | phased release of an update over seven days | | Who is covered | users eligible for the update on that track | users receiving **automatic** updates; anyone can still update manually | | Stopping | **halt** the rollout | **pause** the phased release | | Undoing | not possible: no downgrade | not possible: no downgrade | The console mechanics belong to each store's own tooling; the Flutter-specific point is what those controls cannot do. ## What a halt does not undo A halt or pause **stops further distribution**. It does not remove the build from devices that already updated, and neither store downgrades users to the previous version. Recovery is therefore forward-only: 1. Build a new release, often by reverting the redesign in source. 2. Give it a new, **higher** version than the bad build (the `+N` build number in `pubspec.yaml`'s `version`, or the version name too): Play refuses a `versionCode` that is not higher than one already uploaded, and App Store Connect will not take a reused version and build number. 3. Submit it through review and roll it out, possibly faster than usual. A team that assumes "halt means rollback" leaves the affected share of users on the broken screen while it discovers this. ## Designing the release so reverting needs no review The more robust plan decouples **shipping the code** from **turning it on**: - Compile **both** the old and the redesigned home screens into the binary. - Pick one at runtime from a value fetched at startup, for example a remote configuration flag, with the old screen as the safe default when the fetch fails. - Stage the binary, then enable the redesign for a growing share of users by flag. - If refill completion drops, turn the flag off; every updated user returns to the old screen on the next launch without a new build. Store rollout percentage controls **which binary** people have; the flag controls **which screen** they see. Using both gives two independent brakes. ## A timeline for the pharmacy redesign 1. Ship build N with both home screens compiled in and the flag defaulting to the classic screen. 2. Roll build N out on Play in stages and let the App Store phase it; nothing visible changes yet. 3. Once build N has reached most users, enable the redesign for a small share by flag and compare refill completion against the classic screen. 4. Widen the flag in steps; if a metric drops, switch it off and investigate. 5. In a later build, delete the classic screen and the flag once the redesign has proved itself, so the dead path does not linger. ## What to watch while staged - **Crash-free users per version and build number**, with release symbols uploaded so obfuscated Dart stack traces can be read. - **Business signals** for the redesigned flow, such as prescription-refill completion and time to reach the refill action. - **Platform differences**: Android percentages and iOS automatic-update pacing grow at different rates, so compare like with like. ## Things that are easy to get wrong - Assuming the App Store phase covers everyone; manual updates bypass it. - Treating a staged rollout as a substitute for testing; it limits blast radius, it does not find bugs. - Forgetting that a flag-gated old screen must still work against the current backend, or the safe default is not safe.
- The Play rollout of the Flutter pharmacy app was halted at 10 percent. How do those users get the old home screen back?Only through a newer build. Build the previous home screen from source, give it a higher build number than the halted release, submit it and roll it out. Play does not downgrade users, and the halted build stays on their devices until the new one arrives, unless a runtime flag in that build can already switch screens.
- Why does the App Store's phased release not guarantee that only a fraction of iOS users see the new Flutter build?Phased release paces automatic updates only. Anyone who opens the App Store and updates manually gets the new version immediately, and new downloads get the new version. Treat it as a brake on automatic updates, not as a hard cohort limit.
- Could the pharmacy team push a fixed Dart file to users without a store release?Not with Flutter as shipped. Release builds contain AOT-compiled Dart, and the app does not load new Dart code at runtime. What can change without a release is data the existing code reads, such as a remote flag that picks between two screens already compiled in.
A staged rollout is like opening a new pharmacy counter to a few customers first: closing the counter stops new customers arriving, but anyone already served has taken the medicine home. A switch behind the counter that sends everyone back to the old counter is the runtime flag.
saying these in an interview costs you the question
- Halting a staged rollout rolls affected users back to the previous version.
- A Flutter release can be hot-reloaded from the server to fix the bug.
- The App Store phased release stops manual updates too.
- A rollback build can reuse the old build number.
- A staged rollout replaces testing on real devices.