New in v2.0.0

Code Push

Push config overrides, feature flag overrides, and asset updates to your Flutter app instantly — no App Store or Play Store release required.

What Code Push does

Koolbase Code Push lets you deploy Runtime Bundles — versioned, signed packages containing config overrides, feature flag overrides, directives, and assets. On cold launch, the SDK checks for an available bundle, downloads it in the background, verifies its integrity, and activates it on the next launch.

Once a bundle is active, all existing SDK accessors — Koolbase.configInt(), Koolbase.isEnabled(), etc. — transparently return bundle values. No code changes required in your app.

What can be updated via Code Push

  • Config values (timeouts, limits, URLs, thresholds)
  • Feature flag overrides (enable/disable features per bundle)
  • Directives (fire-once commands like force_logout_all)
  • Assets (images, JSON files, fonts)
  • Compiled Dart code or Flutter widgets (requires a store release)
  • Native plugins or Android/iOS permissions

App Store compliance

Koolbase Code Push only updates config, flags, and asset files — not native binaries or compiled Dart code. This keeps it fully compliant with Apple App Store and Google Play Store guidelines.

How it works

  1. You deploy a bundle via the Koolbase dashboard or CLI
  2. On cold launch, the SDK calls GET /v1/code-push/check
  3. If a newer bundle exists for this app version, platform, and channel — the SDK downloads it
  4. The SDK verifies the SHA-256 checksum before caching
  5. On the next cold launch, the bundle is promoted to active and its values override Remote Config and Feature Flags

Merge precedence

Bundle values win over all other sources. The full precedence chain is:

App defaults → Remote Config → Runtime Bundle (wins)

Only keys present in the bundle are overridden — the bundle does not wipe your Remote Config layer.

Setup

Add codePushChannel to your KoolbaseConfig. That's the only change required.

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

// After initialize() returns, bundle overrides are already active.
// Use SDK accessors as normal — they transparently return bundle values.
final timeout = Koolbase.configInt('api_timeout_ms', fallback: 3000);
final newCheckout = Koolbase.isEnabled('new_checkout_flow');

Activation timing

Bundles activate on the next cold launch, not immediately. On the current launch, the SDK downloads the bundle in the background. On the following launch, it is promoted to active before the first frame renders.

Bundle format

A Runtime Bundle is a .zip file with a specific structure. When using the CLI, this is created automatically. When building manually, follow this layout:

bash
bundle/
├── config.json       # Config overrides (key-value pairs)
├── flags.json        # Flag overrides (key: true/false)
├── directives.json   # Fire-once commands
└── assets/
    ├── images/
    ├── json/
    └── fonts/
json
// config.json
{
  "api_timeout_ms": 8000,
  "max_retry_count": 5,
  "support_url": "https://help.myapp.com"
}

// flags.json
{
  "new_checkout_flow": true,
  "legacy_auth": false,
  "dark_mode_beta": true
}

// directives.json
{
  "force_logout_all": false
}

Deploying via CLI

The koolbase bundle deploy command packages your bundle directory, creates a draft, uploads the artifact, and publishes — all in one command.

bash
koolbase bundle deploy \
  --app <project_id> \
  --platform ios \
  --channel stable \
  --base-app-version 1.2.0 \
  --max-app-version 1.2.99 \
  --bundle-dir ./bundle \
  --rollout 10

The --rollout flag controls what percentage of eligible devices receive this bundle. Start with a low percentage and increase as confidence grows.

bash
# List all bundles for an app
koolbase bundle list --app <project_id>

# Recall a published bundle (devices revert on next cold launch)
koolbase bundle recall --app <project_id> --bundle <bundle_id>

# Dry run — validate and package without uploading
koolbase bundle deploy ... --dry-run

Deploying via Dashboard

  1. Go to your project → Code Push
  2. Select the channel (stable or beta) and platform
  3. Click Deploy Bundle
  4. Fill in the version range, rollout percentage, config JSON, and flags JSON
  5. Click Deploy — the bundle is live immediately

Version range

base_app_version and max_app_version define which app versions can receive this bundle. A bundle targeting 1.2.0 → 1.2.99 will never be served to a user on 1.3.0. Both fields are required — there are no open-ended bundles.

Rollout & recall

Rollout is controlled at the bundle level. A bundle with rollout_percentage: 10 is served to 10% of eligible devices — deterministically, based on device ID. The same device always falls in or out of the rollout for a given bundle.

Only one bundle can be published per app + platform + channel at a time. Publishing a new bundle automatically recalls the previous one.

To roll back, recall the current bundle from the dashboard or CLI. Devices on that bundle will revert to the previous archived version on their next cold launch.

Rollback behaviour

When a bundle is recalled, devices receive a rollback response on their next check. The SDK deletes the active bundle and restores the archived previous version. If no previous version exists, the app falls back to its built-in defaults.

Accessing bundle data directly

You can access the code push client directly if you need more control.

dart
// Check if a bundle is active
if (Koolbase.codePush.hasActiveBundle) {
  final manifest = Koolbase.codePush.activeManifest!;
  print('Bundle v${manifest.version} active');
  print('Config: ${manifest.payload.config}');
  print('Flags: ${manifest.payload.flags}');
}

// Register a directive handler
Koolbase.codePush.onDirective('force_logout_all', (value) {
  if (value == true) {
    Koolbase.auth.signOut();
  }
});

// Access override engine directly
final override = Koolbase.codePush.override;
final timeout = override.getConfig('api_timeout_ms');
final flagEnabled = override.getFlag('new_checkout_flow');

Channels

Channels let you control which bundles different users receive. The most common setup:

ChannelUse case
stableProduction users. Deploy here when confident.
betaInternal testers or early adopters. Deploy here first.

Set the channel in KoolbaseConfig at initialization time. Bundle versions are independent per channel — stable v3 and beta v3 are separate sequences.

API reference

Method / PropertyDescription
Koolbase.codePushAccess the code push client.
Koolbase.codePush.hasActiveBundleTrue if a bundle is currently active.
Koolbase.codePush.activeManifestThe active BundleManifest, or null.
Koolbase.codePush.overrideThe RuntimeOverrideEngine instance.
Koolbase.codePush.onDirective(key, handler)Register a handler for a directive key.
Koolbase.configInt(key)Returns bundle value if present, else Remote Config, else fallback.
Koolbase.configString(key)Same precedence chain as configInt.
Koolbase.configBool(key)Same precedence chain as configInt.
Koolbase.isEnabled(flagKey)Returns bundle flag if present, else Feature Flag evaluation.