Flutter Versions & Engines

VM Patches require your app to be built with a Koolbase engine that matches your Flutter version exactly. Koolbase publishes prebuilt, signed engines you install with one command. This page covers how to get one, why versions must match, and which platforms are supported. (Runtime Bundles have no such requirement — they work on any Flutter build.)

Installing a Koolbase engine

You don't build the engine yourself. Koolbase publishes prebuilt engines to its registry, and you install the one for your Flutter version with a single command. It downloads the engine, verifies its signature, and installs it locally.

# Install the Koolbase engine for your Flutter version
koolbase engine install 3.44.0

See which engines are available, and which you already have installed:

koolbase engine list

Example output (your list reflects the live registry — run the command to see the current set):

Available engines for host macos/arm64, target android/arm64:
 3.44.3-koolbase.1  (flutter 3.44.3, 425 MB)
 3.41.9-koolbase.1  (flutter 3.41.9, 411 MB)
 3.38.10-koolbase.1 (flutter 3.38.10, 404 MB)
 3.35.7-koolbase.1  (flutter 3.35.7, 401 MB)
 3.32.8-koolbase.1  (flutter 3.32.8, 379 MB)
 3.32.1-koolbase.1  (flutter 3.32.1, 379 MB)
 = installed locally
(Earlier patch revisions of each minor are also published run the command for the full list.)

Engines are published per target ABI. The list above is the default android/arm64 target; pass --target-arch arm to see the 32-bit armeabi-v7a engines:

koolbase engine list --target-arch arm
Available engines for host macos/arm64, target android/arm:
 3.44.3-koolbase.1  (flutter 3.44.3, 417 MB)
 3.41.9-koolbase.1  (flutter 3.41.9, 405 MB)
 3.38.10-koolbase.1 (flutter 3.38.10, 398 MB)
 3.35.7-koolbase.1  (flutter 3.35.7, 395 MB)
 3.32.8-koolbase.1  (flutter 3.32.8, 374 MB)
 3.32.1-koolbase.1  (flutter 3.32.1, 374 MB)
 = installed locally
(Earlier patch revisions of each minor are also published run the command for the full list.)

Signed and verified on download

Every engine is signed with Koolbase's Ed25519 key. On install, the downloaded artifact's hash and signature are verified before it's used — so you always build on an authentic, untampered engine.

Which versions are available

Koolbase publishes a version-matched engine for recent stable Flutter releases, on both arm64-v8a and armeabi-v7a. Rather than maintaining a list here that goes stale each Flutter release, the source of truth is the CLI — koolbase engine list shows exactly what's available right now, and koolbase engine install <version> fetches the one matching your app.

  • x86_64 (emulators) isn't available yet — restrict your release ABIs before a Play upload. Store Compliance.
  • Add --target-arch arm to koolbase engine list for the 32-bit set.
  • Need a version or target not listed? [email protected] — added on request.

Why the engine must match your Flutter version

A VM Patch replaces compiled Dart inside the Dart VM. The exact layout of that compiled code — how the snapshot is structured, how the engine reads it, how the build is identified — is tied to a specific version of the Flutter engine and Dart SDK. A patch built for one engine version assumes that layout.

So the Koolbase engine your app ships with, and the engine the patch was built against, must be the same Flutter version. An engine built for one Flutter version cannot safely patch an app built on another — the internals differ. This is why there isn't a single universal Koolbase engine: there's one per supported Flutter version.

Match the exact version, not just the major.minor

Even small version differences matter. Flutter 3.32.0 and 3.32.1 ship different Dart SDK builds with different internals — an engine for one will not match an app built with the other. Always match the precise version your app is built and shipped with.

Finding the version your app ships with

The version that matters is the one that built the binary on your users' devices — which may differ from whatever Flutter is active on your laptop. If your release builds run in CI, check the Flutter version pinned there (a CI config, an fvm pin, or a build image). When in doubt, the ground truth is the shipped artifact itself:

# Read the Dart/engine version baked into a shipped Android build
# (use lib/armeabi-v7a/libflutter.so for a 32-bit build)
unzip -p app-release.apk "lib/arm64-v8a/libflutter.so" \
  | strings | grep -i "stable"

The Dart version string in the binary maps to a specific Flutter release — that's the version you install the matching Koolbase engine for.

Building with a Koolbase engine

Once an engine is installed, build your release with koolbase build. It wraps flutter build with the correct engine flags pointing at the engine you installed — you don't manage those yourself. The output is a normal release artifact, just built on the Koolbase engine and stamped with a build_id.

# Build using a version-matched Flutter SDK
koolbase build android --release --flutter-sdk ~/flutter-3.44.3

# Or select a specific installed engine explicitly
koolbase build android --release --engine 3.44.3-koolbase.1

# Target 32-bit ARM (armeabi-v7a) instead of the arm64 default
koolbase build android --release --engine 3.44.3-koolbase.1 --target-arch arm

Shipping to the Play Store: use release android

koolbase build android above builds one ABI at a time. To produce a single multi-ABI .aab (arm64-v8a + armeabi-v7a) and register a release for each in one step — the artifact you upload to Google Play — use koolbase release android, then koolbase patch android for over-the-air updates. See the CLI Reference.

The Flutter SDK must match the engine

The engine is built for a specific Flutter version, so your local Flutter SDK must be that same version (e.g. an engine for Flutter 3.44.0 needs the 3.44.0 SDK). Point Koolbase at the matching SDK with --flutter-sdk, or save it once so you don't repeat it on every build.

Build once, then freeze it

The binary you ship to the store is the base every future patch is diffed against. Build it once, ship that exact artifact, and keep it — don't rebuild the base between releases, because a rebuild can change the build_id and break patch matching. See Releases & Patches.

Platform support

  • AndroidFully supported for VM Patches. Flutter 3.32–3.44 on arm64, plus armeabi-v7a (32-bit ARM) for 3.32.1 and 3.35–3.44.
  • iOSFully supported for VM Patches on Flutter 3.44 (arm64). Patches are delivered as signed bytecode and applied before the app's first frame on cold launch.

iOS patches work differently from Android under the hood, by design. Apple permits downloaded interpreted code but not downloaded compiled code, so iOS patches ship as signed bytecode that the Koolbase engine's interpreter executes — never as downloaded machine code. Each patch is Ed25519-signed and pinned to the exact binary it was built for; a patch that fails verification, or that a subsequent App Store update has invalidated, is quarantined automatically and the app boots its built-in code. App Store policy also narrows what you should ship this way: bug fixes that don't change your app's primary purpose, not feature delivery. See Store Compliance for the policy details.

Runtime Bundles are cross-platform today

The platform constraints on this page apply only to VM Patches. Runtime Bundles (config, flags, assets) work on any Flutter build, on every platform, with no engine requirement.

Upgrading Flutter versions

When you upgrade your app to a new Flutter version, install the matching Koolbase engine for that version, then build and ship a new release on it. Patches are then built against that new release. Each shipped Flutter version is effectively its own line of releases and patches — a patch for your 3.32 build doesn't apply to your 3.35 build, and shouldn't.