Staged rollouts for Flutter apps on Google Play
By Ann Tech · 6 February 2026
Staged rollouts on Google Play let you release an update to a small percentage of users, watch for crashes and negative reviews, then gradually expand. If something goes wrong, you halt instead of replacing a working release for everyone.
Why staged rollouts matter
No amount of testing catches every device/OS combination. A bug affecting 0.1% of Android devices can mean thousands of crashes at scale. Staged rollouts surface that before it hits everyone.
Configuring in the Play Console
Play Console → Your App → Release → Production → Create new release.
After uploading your AAB, in the "Roll out release" step:
- Click "Set rollout percentage"
- Set the initial percentage (10% is common)
- Submit release
Users are selected randomly and persistently — the same users stay in the rollout as you expand.
Expanding or halting
To expand: Production → Manage rollout → Increase rollout percentage.
To halt: Manage rollout → Halt rollout. Halting stops new users from getting the update but does not roll back existing installs.
Automated rollout with Fastlane
# fastlane/Fastfile
lane :deploy_staged do
supply(
track: 'production',
rollout: '0.1', # 10%
aab: 'build/app/outputs/bundle/release/app-release.aab',
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
)
end
lane :expand_rollout do |options|
supply(
track: 'production',
rollout: options[:percentage] || '0.5',
skip_upload_apk: true,
skip_upload_aab: true,
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
)
end
Usage:
bundle exec fastlane deploy_staged
bundle exec fastlane expand_rollout percentage:0.5 # 50%
bundle exec fastlane expand_rollout percentage:1.0 # 100%
Monitoring during rollout
Android Vitals → Crashes and ANRs — Compare crash rate to previous release. Play flags "bad behaviour" above ~1.09%.
Firebase Crashlytics — Filter by version to isolate new-version crashes:
await FirebaseCrashlytics.instance.setCustomKey(
'app_build_number',
packageInfo.buildNumber,
);
Ratings — A sudden spike of 1-star ratings is a signal to halt immediately.
Rollout decision criteria
| Day | Action |
|---|---|
| Day 0 | Release at 10% |
| Day 1 | Review metrics. If clean → 25% |
| Day 2 | If clean → 50% |
| Day 3-4 | If clean → 100% |
| Anytime | Significant crash rate increase → Halt |
Testing tracks
- Internal testing: up to 100 testers, instant publish (no review)
- Closed testing (Alpha): specific testers, requires review
- Open testing (Beta): public opt-in, requires review
- Production: all users, staged rollout available
lane :deploy_internal do
supply(
track: 'internal',
aab: 'build/app/outputs/bundle/release/app-release.aab',
)
end
Version code strategy
Each release needs a unique versionCode:
flutter build appbundle \
--build-number=$CI_BUILD_NUMBER \
--build-name=2.5.1
Google Play vs App Store phased release
- Google Play: you control the percentage manually, can halt at any time.
- Apple phased release: automatic 7-day rollout (1% → 2% → 5% → 10% → 20% → 50% → 100%). You can pause but can't set a custom percentage.
Common pitfalls
Halting and forgetting. A halted rollout doesn't auto-resume. Check your Play Console weekly for stuck releases.
Treating 10% as safe enough to ignore. 10% of 10,000 daily users is 1,000 users. Low-frequency bugs may not appear in the first 24 hours. Monitor for 48 hours before expanding.
Uploading metadata changes with a rollout. Changing store listing copy while rolling out makes it hard to attribute user behaviour changes. Separate metadata updates from binary updates.
Sign in to like, dislike, or report.