Pushing a fix to production is scary. Pushing a fix to every user at once is scarier. If the fix has its own bug, you've just made things worse for everyone.

Web teams solved this years ago with canary releases and instant rollbacks. Mobile apps usually can't: once a build is in the store, it's out. With over-the-air (OTA) updates for Flutter, you can work the same way web teams do.

Here's the workflow I use with OverPush, a code push service for Flutter.

1. Start small: release to 10%

overpush patch android --rollout-percent 10 overpush patch ios --rollout-percent 10 

Only 10% of devices get the update. The same devices stay in the 10% over time, so when you go to 50%, the first group keeps the update and new devices join.

2. Watch the numbers

The dashboard shows, for each patch:

  • how many devices downloaded it
  • how many are running it
  • how many failed, and why

Give it an hour or a day, depending on how many users you have.

3. Go wider

Patch numbers count up per release, so if this is patch 4:

overpush patches rollout 4 --percent 50 overpush patches rollout 4 --percent 100 

Devices see the new percentage the next time they open the app.

4. Something's wrong? Pull it back

If the patch is bad and the original release code was fine:

overpush patches revoke 4 --reason "checkout total wrong" 

On their next launch, devices delete the patch and run the release's own code again.

If patch 4 is bad but patch 3 was fine:

overpush patches rollback --to 3 

This serves patch 3's code again, so devices that already took patch 4 move off it.

5. What if the patch crashes the app on startup?

You don't have to do anything. If an update stops the app from starting, the phone goes back to the store version on its own, even offline. Then revoke the patch so no other device tries it.

Cheat sheet

Situation Command
Try a fix on a few users first --rollout-percent 5
Fix looks good, go wider patches rollout N --percent 100
Patch is bad, release code is fine patches revoke N
Patch is bad, previous patch was fine patches rollback --to N
Patch crashes on startup Nothing: devices roll back by themselves

All of these also work from the dashboard: open the release, then ⋮ on the patch.

Try it

How do you ship hotfixes today? Curious to hear what other Flutter teams do.