Update Strategies

OtaKit has one set of four policy values and three settings that decide when each one runs. The values — off, shadow, apply-staged, and immediate — describe what happens. launchPolicy, resumePolicy, and runtimePolicy describe when it happens. This guide walks through picking a combination; for the full field list see the Plugin API reference.

The four policy values

  • off — do nothing automatically. Nothing is checked, staged, or applied.
  • shadow — check for the latest update and stage it locally, but never apply it. The current session keeps running on the bundle it already has.
  • apply-staged — apply a bundle if one is already staged. If nothing is staged, it falls back to shadow behavior for that check.
  • immediate — check, stage, and apply the newest bundle right away when one is available. The reload can land mid-session — and since any release can be escalated with --force-immediate, you rarely need this as the launch or resume default.

When each setting runs

  • launchPolicy — every normal cold start, once the app's runtime lane is already resolved. This is the one most apps tune, since it covers the vast majority of app opens. Default: apply-staged.
  • resumePolicy — when the app returns to the foreground from the background, throttled by checkInterval. Default: shadow.
  • runtimePolicy — cold start specifically when runtimeVersion changes or resolves for the first time. In practice that's the app's first native install, or a native update where you bumped runtimeVersion in the plugin config before that release. Default: immediate, so a fresh runtime lane catches up fast instead of waiting on a bundle staged under the old lane.

Recommended combinations

Hosted default — right for most apps

runtimePolicy: "immediate", launchPolicy: "apply-staged", resumePolicy: "shadow". Fast on first install, seamless between launches, and new bundles are ready to go as soon as a session restarts.

Update quietly, reload only with consent

Set launchPolicy and resumePolicy to shadow. Bundles stage in the background and nothing ever activates on its own — show a "restart to update" prompt from the updateStaged event and call apply() on accept (see Events & Listeners).

Full manual control

Turn all three policies off and drive the lifecycle yourself with check(), download(), and apply(). Use this when your app owns the entire update experience — see the Manual Flow section of the Plugin API reference.

Ship critical fixes instantly

This one isn't a config — it's per release. Mark it force immediate in the dashboard's release dialog or with otakit release --force-immediate: the flag is baked into the signed manifest, and devices on shadow or apply-staged escalate that one release to immediate — download, apply, and reload on their next check. No rebuild, no config change.

It's "immediate on the next check", not push, and the trial/rollback safety net still applies. Policies set to off never fetch a manifest, so they never see the flag. Because the reload can land mid-session, reserve it for broken releases — not routine rollouts.

Also see Channels & Runtime Version for how rollout audience and native compatibility lanes interact with these policies.