Test an OTA update
Change an installed app without rebuilding it, then roll back the update.
Install a Release build, change its text and image through an OTA update, then restore the original screen. You only build the native app once.
Before you start
- Complete Connect your app. This walkthrough uses its Check and apply update button.
- Use an unused test channel, such as
ota-test. Set the native channel before building, so existing updates cannot replace your starting screen. - Add the text OTA baseline and a local image to a screen you can easily open.
From the app directory, run Doctor with your deployed server URL and fix any reported setup issues:
npx hot-updater doctor --server-base-url https://updates.example.comKeep the full provider path in the URL. Doctor checks native setup and server version; the app test below checks that your client can actually receive and apply an update.
1. Install a Release build
Choose your project's build tool. Run the command for the platform you want to test on a simulator, emulator or connected device.
For iOS, install the native dependencies with your project's CocoaPods setup, then build:
cd ios
pod install
cd ..
npx react-native run-ios --mode ReleaseFor Android:
npx react-native run-android --mode ReleaseUse your equivalent Release command if the app has custom schemes or flavors. The app must load its bundled JavaScript; a development session using Metro does not exercise OTA loading.
You should see OTA baseline and your original image. Keep this app
installed for the remaining steps.
2. Publish a visible change
Change the text to OTA verified and replace the local image with a visibly different one. Leave native code, dependencies and the native app version unchanged. Do not rebuild or reinstall the app.
Publish to the same platform, test channel and compatibility target as the
installed app. These examples use iOS and version 1.0.0; substitute your
actual values. For Android, use -p android.
Use the native app version of the Release build you just installed:
npx hot-updater deploy -p ios -c ota-test -t 1.0.0You should see Deployment successful and an ID. Save that ID for the
application and rollback checks. Leave rollout at its default 100%, which also
includes installations with a named cohort. For a test limited to selected
cohorts, see Rollout & Cohorts.
3. Apply it in the app
Return to the same installed Release app:
- Tap Check and apply update.
- Wait while the app downloads the update and restarts.
- Confirm that OTA verified and the new image both appear.
After the restart, compare the screen's Update ID with the ID from
deployment. The example reads it with
hotUpdater.getBundleId().
Keep the visible screen change as proof too: an ID can change when an update is
staged, before its JavaScript is running.
4. Roll back the test update
Use the ID you saved above. Inspect it first and confirm it belongs to your test channel, then disable it:
npx hot-updater bundle show <id>
npx hot-updater bundle disable <id>In the app, tap Check and apply update again and wait for the restart. The example flow applies the selected rollback through the same button.
You should see OTA baseline and the original image again. This assumes
the channel had no earlier updates. If it did, the app may return to a previous
compatible enabled update instead.
This tests disabling an update. Automatic crash rollback is a separate recovery mechanism.
Finish the check
Keep a short record of the platform, channel, deployment ID and what you saw:
| Check | Expected result |
|---|---|
| Native build | Original text and image appear in a Release app |
| OTA update | New text and image appear after restart, with the deployment ID |
| Rollback | Original screen returns after disabling the test update |
If the app runs the Insights plugin, verify its reports in the Console: confirm the application and rollback reports arrived for your test channel. Repeat the walkthrough for each platform you support.
You can now explore update timing, required updates and production channels.
If something goes wrong
| What you see | What to do next |
|---|---|
| Update failed | Check the app's URL and client key with client-access diagnostics |
| Button becomes available again, screen unchanged | Inspect the deployment with bundle show; platform, channel, version/fingerprint and cohort must match the app |
| New ID, old screen | Wait for the download and restart to finish; check app logs if the restart fails |
| New screen disappears after restart | Check startup errors and crash history |
HotUpdater.init() configures the client at module scope and returns the
instance the button uses. The button starts the check, download and restart. Keep the sample's shared error reporter so request,
download and restart failures are visible.