Code Push

Ship fixes to your live app in minutes instead of waiting days for store review. Koolbase Code Push delivers updates over the air — from a one-line config toggle all the way to a real fix in your compiled Dart code — without pushing a new build to the App Store or Play Store.

Not on Flutter Web

Code push patches a compiled binary; a browser has none. On the web Koolbase.isCodePushAvailable is false and Koolbase.codePush throws rather than pretending. Everything on this page applies to the iOS and Android builds you ship.

Two modes, one integration

Code Push has two layers that solve different problems. You don't choose between them or wire them up separately — a single Koolbase.initialize() turns both on, and you reach for whichever fits the change you're shipping.

Runtime Bundles

KoolbaseCodePushClient

Versioned, signed packages of config values, feature-flag overrides, directives, and assets. The SDK downloads a bundle on launch and your existing accessors — Koolbase.configInt(), Koolbase.isEnabled() — transparently return the new values. No rebuild, nothing to recompile. Use it to tune timeouts, flip features, or swap content packs.

VM Patches

KoolbaseVmPatchClient

Patches to your compiled Dart code itself. When you have an actual bug in your logic — a wrong calculation, a crash, a broken flow — you fix the Dart, build a patch, and push it. The Koolbase Flutter engine verifies and applies it on the next launch, before any of your code runs — on iOS, before the app's first frame. Supported on Android and iOS. This is the part that changes app behavior, not just configuration.

Which one do I use?

If the change is a value you could have read from a config — a limit, a URL, a toggle — use a Runtime Bundle. If the change is code you'd normally fix in .dart and re-ship through the store — use a VM Patch. Both arrive over the air; they just operate at different layers.

Enabling Code Push

There's no separate setup. Both modes initialize as part of the standard SDK bootstrap:

main.dart
dart
import 'package:koolbase_flutter/koolbase_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Koolbase.initialize(
    KoolbaseConfig(
      baseUrl: 'https://api.koolbase.com',
      publicKey: 'pk_live_...',
      codePushChannel: 'stable',
    ),
  );

  runApp(const MyApp());
}

On launch, the SDK checks for an available Runtime Bundle and stages any VM patch that matches the running binary. Bundles apply immediately to your accessors; VM patches apply on the next cold launch, after the engine has verified them. Both happen in the background — your app keeps running while updates download.

VM Patches need the Koolbase engine

Runtime Bundles work with any Flutter build. VM Patches require your app to be built with the Koolbase Flutter engine (via koolbase build) for the patch matching your app's Flutter version. See Flutter Versions & Engines for why, and Quick Start to set it up.

What you can push

Supported

  • Config values — timeouts, limits, URLs, thresholds (Runtime Bundle)
  • Feature-flag overrides — enable or disable features per bundle (Runtime Bundle)
  • Directives — fire-once commands like force-logout (Runtime Bundle)
  • Assets — images, JSON, fonts (Runtime Bundle)
  • Compiled Dart code — bug fixes to your app logic (VM Patch)
  • Adding, removing, or changing a Dart package used by your code (VM Patch, Android)

Not supported — these still require a store release

  • Native code — Kotlin/Java on Android, Swift/Objective-C on iOS
  • Native plugins, new permissions, or changes to the app manifest
  • The Flutter engine itself, or the Dart SDK version
  • Anything that changes your app's primary purpose (see Store Compliance)

How VM Patches stay safe

Replacing compiled code on a user's device is only acceptable if it can never brick the app. Every VM patch carries layered protection, all enforced by the engine before a single line of your Dart runs:

  • Signature verification. Every patch is Ed25519-signed. The engine rejects anything not signed by your key.
  • Build-id matching. A patch is bound to the exact binary it was built against. A patch meant for a different build is rejected, not misapplied.
  • Reconstructed-target verification. For diff patches, the engine rebuilds the full target and checks its hash before loading it — a corrupt or wrong patch fails this check and is discarded.
  • Crash-revert. If an applied patch fails to boot cleanly, the app automatically falls back to the last known-good code on the next launch.

Smaller patches, faster delivery

VM patches ship as binary diffs against the installed build — typically tens of kilobytes rather than megabytes, so updates reach your users quickly even on slow connections.

A note on the stores

Both modes are designed to stay within App Store and Play Store rules — but staying compliant depends on how you use them. Code Push is for fixes and tuning, not for shipping major new features around store review. Before you push to a production app, read Store Compliance.