Skip to content

Create a Patch

Once you have published a release of your app, you can push updates using one of the shorebird patch commands.

shorebird patch android --track=stable

Patching multiple platforms simultaneously

Section titled “Patching multiple platforms simultaneously”

If your app supports multiple platforms, you can build and publish patches for them in a single command using the --platforms (or -p) option:

shorebird patch --platforms=android,ios --track=stable

This will build and promote the patches for the specified platforms to their respective releases in one step.

This will do several things:

  1. Downloads the corresponding release artifacts.
  2. Builds the artifacts for the update.
  3. Generates a patch using the diff between the release and the current changes.
  4. Uploads the patch artifacts to the Shorebird backend.
  5. Publishes the patch to the track you pass with --track or choose when asked. See Tracks.

Example output:

$ shorebird patch android --release-version 0.1.0+1 --track=stable
✓ Fetching app (0.2s)
✓ Fetching releases (0.1s)
✓ Fetching release artifacts (0.3s)
✓ Fetching aab artifact (0.1s)
✓ Fetching android_supplement artifact (0.1s)
✓ Downloading aab (100%) (1.9s)
Building patch with Flutter 3.47.9 (8352242a91)

Running Gradle task 'bundleRelease'...                             41.2s
✓ Built build/app/outputs/bundle/release/app-release.aab (21.4MB)
✓ Verifying patch can be applied to release (0.4s)
✓ Downloading release artifact 1/3 (100%) (0.5s)
✓ Downloading release artifact 2/3 (100%) (0.5s)
✓ Downloading release artifact 3/3 (100%) (0.5s)
✓ Creating patch artifacts (2.1s)

🚀 Ready to publish a new patch!

📱 App: My App (61fc9c16-3c2b-4a6f-9d1e-2f8a7b5c4d3e)
📦 Release Version: 0.1.0+1
🕹️  Platform: Android [arm32 (161.78 KB), arm64 (166.20 KB), x86_64 (161.51 KB)]
🟢 Track: Stable

✓ Creating patch (93ms)
✓ Uploading artifacts (1.5s)
✓ Fetching channels (86ms)
✓ Promoting patch to stable (78ms)

✅ Published Patch 1!

Each patch is for one release version. See Release versions for how Shorebird uses your app’s version.

To choose the release, pass --release-version:

shorebird patch android --release-version 0.1.0+1 --track=stable

--release-version latest targets the most recently updated release for that platform:

shorebird patch android --release-version latest --track=stable

Without --release-version, shorebird patch asks you to pick a release when it runs in a terminal. When it can’t ask, as in CI, always pass --release-version. Without it, shorebird patch builds the app an extra time and reads the release version from the build. Shorebird 1.6.137 and newer warn that this guessing is deprecated and will be removed in a release after January 1, 2027, then build the patch again with the release’s settings. Shorebird 1.6.136 and older could reuse the first build as the patch, without the release’s settings, such as obfuscation. An Android archive (aar) or iOS framework for add-to-app has no version to read, so pass the host app’s release version.

In CI, pass the exact version of the release your users have, such as --release-version 1.0.0+1, when you might have a newer release that hasn’t shipped yet. latest targets the most recently updated release, which may be that newer one.

A patch is built with the Flutter version of its release and can’t change it. Shorebird 1.6.135 and newer warn when that version has a known problem on the platform you’re patching, such as the iOS crash in Flutter 3.44.

If your application supports flavors or multiple release targets, you can specify the flavor and target using the --flavor and --target options:

shorebird patch android --target lib/main_development.dart --flavor development --track=stable

A patch uses the build flags of its release

Section titled “A patch uses the build flags of its release”

A patch must be built with the same --dart-define and --dart-define-from-file values, and the same --target, as its release. Otherwise an iOS or macOS patch may fail to link, and on any platform the patch may change the values compiled into code it didn’t mean to touch. Shorebird 1.6.138 and newer record them when you release and check them when you patch. If they differ, shorebird patch warns, and asks or stops; see Patch stops because its flags don’t match the release.

Shorebird stores each define’s key, a SHA-256 hash of its value, and a hash of the target path, not the values themselves. The hash isn’t salted, so a short or guessable value can be found by trying candidates: don’t rely on it to keep a define secret. A release isn’t checked if it was made with an older version, or if its recorded flags are missing, unreadable or from a newer CLI. Run with --verbose to see when an unreadable or newer record skips the check.

The options on this page cover most patches: --release-version, --track, --platforms, --flavor and --target. A few others come up often:

  • --rollout offers the patch to a percentage of the devices on its track, such as --rollout 10, instead of every device on it. Devices on releases built with a Flutter older than 3.35.7 get it only at 100%. It needs Shorebird 1.6.139 or newer; see Percentage-Based Rollouts.
  • --dry-run (-n) builds and checks the patch without uploading it, which is useful in CI.
  • --export-options-plist points an iOS patch at the same ExportOptions.plist as its release.
  • --min-link-percentage sets how much of an iOS patch’s Dart code must run natively rather than in the interpreter. Shorebird 1.6.135 and newer default to 20; 0 accepts any patch. See Link percentage and slow patches.
  • --allow-native-diffs and --allow-asset-diffs publish a patch even when Shorebird detects native or asset changes. They’re not recommended: a patch can’t change native code or assets. --allow-build-flag-diffs builds a patch even when its defines or target differ from the release’s; see A patch uses the build flags of its release.

Run shorebird patch --help for every option.

Patching an application on these platforms has no effect on performance. A patch replaces your app’s compiled Dart code with a newly compiled version, so all of it runs on the CPU as before.

Patching an application on iOS typically does not affect application performance. However, the patching mechanism on iOS is different from other platforms. Unchanged code runs as normal (on the CPU), changed (or added) code will run in a Dart interpreter (slower than the CPU). Typically this change is undetectable, but if you are changing particularly performance-sensitive Dart code (e.g., code for processing images, or large datasets), you may see a performance difference after patching.

You can always test your patches before sending them to users by staging patches. For a detailed look at how iOS patching works, see System Architecture.

If you ever see unexpected performance changes when patching, please reach out for help.


You can manage your patches directly from the command line using the shorebird patches commands.

To list all patches associated with a specific release version:

shorebird patches list --release-version 1.0.0+1

This will display a list of all patches published for that release, their patch numbers, active status, and tracks.

To view detailed information for a specific patch number:

shorebird patches info --release-version 1.0.0+1 --patch-number 1

This command shows the patch’s ID, track, whether it is rolled back, any notes, and the size of each platform and architecture artifact.

If you published a patch to a staging track (e.g., staging) and verified it works correctly, you can promote it directly to the stable track using:

shorebird patches promote --release-version 1.0.0+1 --patch-number 1

promote is set-track with the track defaulting to stable. Older CLIs run the same command but print a deprecation warning, and its --track, --channel, --app-id, and --json flags need Shorebird 1.6.130 or newer.

To assign a patch directly to a specific deployment track (e.g., promoting or routing to a staging beta group):

shorebird patches set-track --release-version 1.0.0+1 --patch-number 1 --track staging

The --release-version and --patch-number flags of set-track need Shorebird 1.6.128 or newer. On an older CLI, use --release and --patch instead, or run shorebird upgrade first.

promote and set-track take --rollout too (Shorebird 1.6.139 or newer), to put the patch on the track at a percentage of its devices, such as --rollout 10.

To offer a patch that’s rolling out to more of the devices on its track, run:

shorebird patches rollout --release-version 1.0.0+1 --patch-number 1 --percentage 50

A rollout only goes up, and 100 offers the patch to every device on its track. shorebird patches rollout needs Shorebird 1.6.139 or newer. See Percentage-Based Rollouts.

To stop serving a patch, roll it back. To serve it again later, roll it forward:

shorebird patches rollback --release-version 1.0.0+1 --patch-number 1
shorebird patches rollforward --release-version 1.0.0+1 --patch-number 1

See Roll back a Patch for what happens on devices and the options these commands take.

Individual patches can’t be deleted. A patch is removed along with the release it belongs to, or the app that owns that release. Those deletions are permanent, and the console asks you to confirm before anything is removed.

See Delete Apps, Releases, and Patches for details.