🚀 Code Push / Over-the-Air (OTA) Updates in Flutter (with Shorebird)



🚀 Code Push / Over-the-Air (OTA) Updates in Flutter (with Shorebird)


One of the biggest pains in mobile development is publishing updates. Even for the smallest text fix, you need to:

  • Rebuild the app.

  • Upload it to Google Play Store / App Store.

  • Wait for review and approval.

  • Wait for users to update manually.

That’s a slow loop.

Now imagine you could ship that fix instantly to all users, without waiting for store approvals. That’s exactly what Code Push (Over-the-Air updates) gives you.

And in Flutter, this is possible with Shorebird, a project started by former Flutter team members.

This blog will cover:

  • ✅ What Code Push / OTA updates mean.

  • ✅ How Shorebird makes it work in Flutter.

  • ✅ Step-by-step usage with CLI.

  • ✅ Real-world examples (text, logic, assets).

  • ✅ Internals (how it figures out what changed).

  • ✅ Limitations and best practices.


📌 What is Code Push / OTA Update?

Code Push (a.k.a. OTA update) is a way to update parts of your app remotely — without resubmitting to app stores.

  • It’s not a full binary replacement.

  • Instead, it only updates Dart code and assets.

  • Think of it like a hotfix pipeline that bypasses the store.


📌 Why Use Code Push in Flutter?

  • 🛠️ Instant bug fixes → no app store delays.

  • 🌍 Global rollouts → every user gets the update immediately.

  • 🎨 A/B test features or UI → without separate releases.

  • 💸 Fewer releases to maintain → store updates only for native changes.


⚙️ How a Flutter App Normally Works

When you build your Flutter app:

  • Dart code is AOT-compiled (Ahead-of-Time) into machine code.

  • On Android → this becomes a .so shared library.

  • On iOS → bundled in .app.

  • Assets → packed in flutter_assets/.

These are frozen at build time. Any change means a new build + new store release.


⚙️ How Shorebird Works Behind the Scenes

Shorebird tweaks the Flutter runtime so that instead of always using the bundled Dart snapshot, it can swap in a patched version delivered over the air.

Here’s the flow:

  1. Initial Release
    You build and release normally (via shorebird release android).

  2. Make a Change
    You fix your Dart code or update an asset.

  3. Patch Creation
    Run shorebird patch android.

    • Shorebird compares the compiled Dart snapshot of the new code against the last release.

    • Extracts only the diff (changed instructions + assets).

  4. Patch Delivery

    • Uploads patch to Shorebird’s server.

    • Users’ apps check for patches on launch.

  5. Patch Application

    • Patch is downloaded.

    • Stored locally.

    • On next app run → new Dart snapshot is loaded.


⚙️ Example: Text Change in Real App

Initial Code (v1.0)

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text("Version 1.0 - Hello World!"),
      ),
    );
  }
}

You release this via:

shorebird release android

Later Fix (v1.1)


class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text("Version 1.1 - Hello from OTA Update!"),
      ),
    );
  }
}

Instead of a full rebuild:

shorebird patch android
  • Only the compiled instructions for that Text widget change.

  • Shorebird creates a patch with those changes.

  • Users see "Version 1.1 - Hello from OTA Update!" instantly on next app launch.


⚙️ Updating Assets (Example)

Suppose you ship assets/config.json with:

{ "theme": "light" }

Later, you want to change it to:

{ "theme": "dark" }

Steps:

  1. Update the file in /assets/config.json.

  2. Rebuild patch:

    shorebird patch android
    
    
  3. Users’ apps download the new asset and start using "dark" config.

✅ Works the same for images, icons, JSON files.


⚙️ How Does It Know What Changed?

Shorebird works at the compiled snapshot level.

  • When you patch, it recompiles Dart into kernel/bytecode snapshot.

  • Compares it against the last release snapshot.

  • Bundles only the diff.

This is similar to how Git stores only changes instead of full files.

So if only one string changes, the patch is very small.


⚙️ What About Rollbacks?

Made a bad patch? No worries.
You can instantly roll back:

shorebird rollback android

Users automatically revert to the last stable snapshot.


⚙️ What Code Push Cannot Do

❌ Add/remove native plugins (e.g., Camera, Firebase, Bluetooth).
❌ Modify AndroidManifest.xml or Info.plist.
❌ Change Gradle or Xcode project settings.
❌ Update native SDK versions.

👉 For those, you still need a full store release.


📌 Shorebird CLI Quick Reference

 
# Initialize project
shorebird init  

# Release first version
shorebird release android  

# Create a patch
shorebird patch android  

# Roll back to previous
shorebird rollback android  

# Check CLI version
shorebird --version 

📌 Real-World Use Cases

  • 🔧 Fix a crash immediately (e.g., null pointer in Dart code).

  • 🌍 Change text translations without waiting for reviews.

  • 🎨 Swap assets (icons, configs) remotely.

  • 📊 Push analytics or experiment code instantly.


📌 Alternatives

  • Microsoft CodePush → for React Native, not Flutter.

  • Custom OTA system → possible, but Shorebird solves distribution, patching, and rollback out of the box.


📌 Conclusion

Code Push / OTA updates are a superpower for Flutter teams.

  • ✅ Dart code and assets → patchable instantly.

  • ✅ Faster release cycles.

  • ✅ Fewer headaches with store approvals.

  • ❌ Native changes still require full releases.

With Shorebird, Flutter finally gets the same agility that web developers enjoy — ship fast, fix fast, experiment fast.

👉 If you haven’t already, try Shorebird and cut your update times from days to minutes.


💡 Pro Tip: Combine Shorebird OTA updates for hotfixes + traditional store releases for native updates → best of both worlds.


Would you like me to also add an architecture diagram (workflow: developer → Shorebird server → user device) to make the blog more visually engaging?

Post a Comment

0 Comments