Guides9 min read

Rollback strategies for Capacitor OTA updates

Automatic rollback, manual rollback, and channel roll-forward: the three ways to recover from a bad live update in Capacitor, when to use each, and how OtaKit makes a broken release a non-event.

OTA updates are only as safe as their recovery story. If a bad bundle can strand users with no way back, the speed isn't worth it. Done right, a broken release becomes a non-event: the app recovers on its own, or you point everyone back to the last good version in seconds. Here are the three rollback strategies for Capacitor apps and when to use each — with OtaKit as the example.

Mental model: OTA that can't roll back is a liability. The goal is that the worst case — a broken bundle — degrades into “users stayed on the old version,” not “users are stuck on a white screen.”

The three strategies at a glance

StrategyCatchesWho triggers it
Automatic rollbackBundles that fail to bootThe device, on its own
Channel roll-forwardBugs that boot fine but misbehaveYou, by re-pointing a channel
Manual device rollbackEdge cases, targeted recoveryYour code, via the plugin API

1. Automatic rollback (the default safety net)

OtaKit keeps three bundles on device — current, fallback, and staged — and treats every freshly activated bundle as unproven. Your app confirms a successful boot with notifyAppReady(). If that call doesn't arrive within the ready window, the device assumes startup failed and reverts to the last known-good bundle by itself.

import { OtaKit } from "@otakit/capacitor-updater";

// call once your app has booted and rendered
await OtaKit.notifyAppReady();

This catches the scariest failure — a bundle that crashes on launch — with zero intervention. Forgetting notifyAppReady() is the most common OTA bug precisely because it makes good updates look like they roll back. See common mistakes.

2. Channel roll-forward (for bugs that boot fine)

Automatic rollback can't catch a bundle that starts cleanly but has a broken checkout or a bad API call. For those, roll forward: re-release the previous known-good bundle to the affected channel. Because a release is just pointing a channel at a bundle id, recovery is as fast as the rollout was.

# point production back at the last good bundle
otakit release <previous-bundle-id> --channel production

Keep a note of your last-known-good bundle id after each release so this is a ten-second action under pressure.

3. Manual device rollback (targeted recovery)

For edge cases — a support-driven fix, a specific device state — you can trigger a reset to the built-in bundle from your own code using the plugin API. This is the escape hatch, not the everyday tool.

How they work together

In practice you rely on all three: automatic rollback as the always-on floor, staged rollouts so channel roll-forward only ever affects a slice of users, and manual rollback for the rare targeted case. Layer them and there's no failure mode without a recovery.

The single highest-leverage habit: always call notifyAppReady(), and always stage rollouts. Those two cover the overwhelming majority of incidents.

Where to go next

See how to test OTA updates (including testing rollback deliberately) and update strategies.

Related docs