Rollout & Rollback

Ship a patch to a slice of your users first, watch it, then widen it — and pull it back instantly if something's wrong. Staged rollout plus fast rollback is what makes pushing to production safe.

Staged rollout

Every patch has a rollout percentage. A patch at --rollout 10 is served to roughly 10% of eligible devices; the rest stay on what they had. The split is deterministic per device — the same device consistently falls in or out of a given patch's rollout, so a user doesn't flip-flop between versions on each launch.

# Start at 10% of devices
koolbase patch push --app <id> --binary base.so --new fixed.so --diff \
  --key ./private.key --platform android --channel stable \
  --rollout 10 --publish

Recommended rollout pattern

Start small (e.g. 10%), watch your crash/error metrics, then increase. Because rollout is deterministic, widening from 10% to 50% adds new devices without disturbing the ones already on the patch.

A patch at --rollout 100 (the default) goes to all eligible devices on the matched release and channel.

Recall (manual rollback)

If a published patch turns out to be bad, recall it. Devices currently on that patch get a rollback instruction on their next check and revert to the prior state — either the previous published patch, or the base binary if there's no earlier patch.

koolbase patch recall --app <project_id> --patch <patch_id>

Recall reverts to the last good state

On recall, a device that was on patch #3 reverts to the highest still-published patch (say #2), or to the unpatched base binary if none remains. The device re-applies the correct prior code authoritatively — it doesn't just “turn off” the patch.

Automatic crash-revert

Manual recall handles bugs you notice. Crash-revert handles the ones you don't catch in time. If an applied patch fails to boot cleanly, the engine automatically falls back to the last known-good code on the next launch — without any action from you.

This is the last line of defense: even a patch that passed signature, build_id, and reconstruction checks but still crashes at runtime cannot trap a user in a broken app. The device self-heals to the previous working version.

Defense in depth

Verification (signature + build_id + reconstructed-target hash) stops corrupt or wrong patches before they load. Crash-revert stops logically broken but valid patches after they load. Together they mean a bad push degrades to “no update” rather than “broken app.”

Mandatory patches

Mark a patch mandatory with --mandatory when every device must apply it — for example, to push an urgent fix for a critical bug. Like all VM patches it still applies on the next cold launch; mandatory signals its urgency so you can prompt users to restart rather than wait.

koolbase patch push --app <id> --binary base.so --new fixed.so --diff \
  --key ./private.key --platform android --channel stable \
  --mandatory --rollout 100 --publish

A safe push checklist

  1. Push to the beta channel first and verify on your own devices.
  2. Push to stable at a low rollout (e.g. 10%).
  3. Watch crash and error rates for the patched cohort.
  4. Widen the rollout in steps to 100%.
  5. If anything looks wrong, recall immediately — crash-revert covers anything you miss.