Guides9 min read

How to test Capacitor OTA updates before you ship them

A repeatable way to test live updates on real devices before production: use a staging channel, verify activation and rollback, and catch native compatibility issues early with OtaKit.

The whole point of over-the-air updates is speed — but shipping an untested bundle to production is how speed turns into an incident. The fix isn't to slow down; it's to have a repeatable way to test an update on a real device before it reaches users. This guide lays out that loop with OtaKit.

Mental model: test the same bundle you'll release, on a real device, through the real update path — then promote that exact bundle. Never rebuild between testing and shipping.

1. Use a staging channel

Channels let you release to an audience that isn't production. Point your test build (or your own device) at a staging channel and release there first:

otakit upload --release staging

Assign a device to the channel at runtime for ad-hoc testing, or bake it into a dedicated test build:

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

await OtaKit.setChannel({ channel: "staging" });

2. Verify the update actually applies

Install the current store build on a real device, then release to staging and confirm the new bundle downloads and activates according to your update policy. Watch for three things:

  • The device picks up the new bundle (check your version indicator in-app).
  • It activates when you expect — silently on next cold start by default, or on a restart prompt if you use foreground UX. See background vs foreground updates.
  • Your app calls notifyAppReady() and the bundle sticks — if it rolls back, the new bundle failed to boot.

3. Deliberately test rollback

The most valuable test is the one everyone skips: prove that a broken bundle rolls back. Temporarily ship a bundle to staging that throws before notifyAppReady(), and confirm the device returns to the previous known-good version on its own. Once you've seen rollback work with your own eyes, you'll trust production releases a lot more. Read rollback strategies for the full picture.

4. Check native compatibility

A bundle that calls native code the installed shell doesn't have will break at runtime. Test the update against the same store build your users are on — not a fresh local build with newer plugins. OtaKit warns at upload time when it detects a dependency mismatch, and runtimeVersion keeps incompatible bundles from reaching old shells.

5. Promote the exact bundle

Once staging looks good, promote the same bundle id to production — don't rebuild, or you're shipping something you didn't test:

otakit release <bundle-id> --channel production

A five-minute staging pass plus a rollback test turns “I hope this works” into “I watched this work.” That's the difference between fast and reckless.

Where to go next

Combine this with staged rollouts for production, and see the channels docs for the full channel API.

Related docs