I Built the Flutter App Update Package I Always Wished Existed (update_checker_plus)
If you’ve shipped a Flutter app to production, you know the pain.
I Built the Flutter App Update Package I Always Wished Existed (update_checker_plus)

If you’ve shipped a Flutter app to production, you know the pain.
A critical bug slips through. You push a fix. But 40% of your users are still on the broken version three days later — because nothing is prompting them to update.
Or worse: you push a breaking API change, and now old versions are crashing silently for thousands of users who have no idea an update even exists.
Every Flutter developer hits this wall eventually. When I went looking for a solution on pub.dev, I found packages that were either too basic, unmaintained, or required me to wrap my entire widget tree just to show a simple dialog.
So, I built **update_checker_plus**—the Flutter app update checker I actually wanted.
What makes it different?
Most version-checking packages do one thing: scrape the App Store or Play Store page, compare versions, and show a generic dialog. That’s fine for hobby projects. But production-grade Flutter apps need more:
- Force updates when you ship a breaking change.
- Maintenance mode when your backend is down.
- Remote control so you can change update behavior without shipping a new app version.
- Staged rollouts to test an update prompt with 10% of users before a full release.
- Offline support so your app doesn’t crash when there’s no network.
- Adaptive UI that actually looks like it belongs in 2026 (Material 3 + Cupertino).
update_checker_plus covers all of it.

The One-Liner Integration
await UpdateChecker.check(context: context);
That’s the entire integration for basic use. The package reads your installed version, fetches the latest from the store, compares them, and shows a beautiful adaptive dialog if an update is available.
For production use, you configure it once at startup:
void main() {
UpdateChecker.configure(
UpdateConfig(
androidPackageName: 'com.example.myapp',
iosAppId: '123456789',
),
);
runApp(const MyApp());
}
Then call check() after your first frame renders. Done.
Remote Config — The Killer Feature
Store scraping works, but it has a fundamental flaw: you can only react after a new version is live on the store. You can’t force an update for a critical security patch that’s still in review. You can’t activate maintenance mode when your database drops at 2 AM.
Remote config solves this. You host a simple JSON file — on AWS S3, a GitHub Gist, Firebase, or your own API — and the package reads it on every check.
{
"android": {
"latest_version": "2.5.0",
"min_required_version": "2.0.0",
"force_update": false,
"release_notes": "• New dashboard\n• Performance fixes",
"rollout_percentage": 100,
"enabled": true
},
"maintenance": {
"enabled": false,
"message": "Back in 30 minutes. Scheduled maintenance."
}
}
Change force_update to true in that file, and every user on an old version gets a blocking dialog the next time they open the app. No App Store review. No waiting.
The package has built-in sources for four backends right out of the box:
// Plain HTTP endpoint
HttpRemoteConfigSource(url: 'https://yourapi.com/update.json')
// Firebase Remote Config
FirebaseRemoteConfigSource(remoteConfig: FirebaseRemoteConfig.instance)
// Supabase table or Edge Function
SupabaseRemoteConfigSource.table(supabaseUrl: '...', anonKey: '...')
// Appwrite database document or Function
AppwriteRemoteConfigSource.database(endpoint: '...', projectId: '...')
Or, implement your own with a single abstract class:
class MySource extends RemoteConfigSource {
@override
Future<RemoteConfigSchema> fetch() async {
final data = await myGraphQLClient.getUpdateConfig();
return RemoteConfigSchema.fromJson(data);
}
}

Update Types & Logic
The package features four clearly defined states:
| Type | Behaviour |
| :--- | :--- |
| `soft` | Optional — user can tap "Later" or "Don't ask again". |
| `force` | Blocking — back button disabled, cannot be dismissed. |
| `maintenance` | Non-dismissible maintenance message, no update button. |
| `none` | App is up to date — nothing shown. |
The resolution logic runs automatically in priority order: maintenance → force → soft → none. You never have to write that logic yourself.
Staged Rollouts
This is one of my favorite features. Set rollout_percentage to 20 in your remote config, and only 20% of your users will see the update prompt.
The decision is stable: the same device always gets the same result across app restarts based on a hash of the package name. Bump it to 50%, then 100% as you gain confidence in your release. No code changes required.
Why not use upgrader?
upgrader is the incumbent package—it has millions of downloads and works fine for simple cases. But it has some friction points:
- You have to wrap your widget tree:
UpgradeAlert(child: myWidget) - No remote config — you can’t change behavior without a new app release.
- Force update support is only partial.
- No built-in maintenance mode.
update_checker_plus is imperative rather than declarative. You call check() wherever makes sense in your app lifecycle, get a fully typed UpdateResult back, and decide exactly what you want to do with it.
Links & Support
- pub.dev: update_checker_plus
- GitHub: abdulhadinaeem/update_checker_plus
If this saves you time, a ⭐ on GitHub goes a long way. Issues and PRs are always welcome!
About the Author
Hi, I’m Abdul Hadi, a Full Stack & Flutter Developer with over 4 years of experience building high-performance mobile and web applications. I specialize in clean architecture, AI/LLM integrations, and building open-source developer tools. I am a verified publisher on pub.dev, maintaining community tools like [update_checker_plus ](https://pub.dev/packages/update_checker_plus)and [widget_recorder_plus](https://pub.dev/packages/widget_recorder_plus). Connect with me on LinkedIn or check out my work on GitHub.
메타데이터
- post_id
- 800288e7bd67
- slug
- i-built-the-flutter-app-update-package-i-always-wished-existed-update-checker-plus-800288e7bd67
- url
- https://medium.com/@abdulhadi4it/i-built-the-flutter-app-update-package-i-always-wished-existed-update-checker-plus-800288e7bd67
- canonical_url
- https://medium.com/@abdulhadi4it/i-built-the-flutter-app-update-package-i-always-wished-existed-update-checker-plus-800288e7bd67
- author_url
- https://medium.com/@abdulhadi4it
- status
- ok
- fetched_at
- 2026-07-13 06:23:13