Shorebird is code push for Flutter. It lets you ship a Dart-only fix to your users in minutes, without an app store review.

Your app ships with the Shorebird runtime included. When you push a patch, Shorebird serves the updated Dart code to devices on their next app launch. The user doesn't have to update from the store. It just happens.

Native code changes (platform plugins, Android/iOS native bits, assets) still require a full store release. Pure Dart changes go instantly. In practice, most of my bug fixes are pure Dart, so Shorebird covers the fixes I need most urgently.

For the full reference, the Shorebird docs.

How it works

You have two things to think about: releases and patches.

A release is a full build you upload to the App Store or Play Store. This is what your users install.

A patch is a Dart-only update that applies on top of a specific release. When you push a patch, Shorebird's CDN starts serving it. Every user running that release gets the patch on next launch.

Why I use it

App review takes 1 to 2 days. That's fine for features. It's not fine for "the app crashes on launch because I shipped a null check in the wrong place". Shorebird closes that gap.

I keep it installed on every production app, even if I only push a patch once a quarter. The one time I need to fix a crash fast, it saves the day.

When to patch, when to release

Patches are for hotfixes, not features. My rule of thumb:

  • Patch it if users are broken right now and the fix is pure Dart. Crash on launch, a paywall that doesn't return, a null check in the wrong place. Minutes matter.
  • Release it if it touches native code, adds a plugin, bumps assets, or it's a new feature. The store review is the right trade for properly versioned code.

Anything that would require a build config change (permissions, deep links, app icon, splash screen) also needs a full release. Shorebird ships Dart, not the shell around it.

The catch

Two things to know up front, both fine once you plan for them.

  • Patches are release-scoped. A patch applies to one specific release. Users on older releases won't get it. That's a feature, not a bug, since it prevents a patch from ever hitting an app it wasn't compiled against.
  • You're on the hook for rollback. If a patch is worse than what it replaced, you roll it back from the dashboard or push a new patch over the top. There's no automatic "revert on crash" system.

I've shipped maybe a dozen patches across my apps. Half were one-line crash fixes, the other half were copy changes or quick UI tweaks I didn't want to wait a day for.