How React Native OTA updates work

Over-the-air updates let a released React Native app download new JavaScript and compatible assets without waiting for another App Store or Google Play review. They are useful for JavaScript bug fixes, small product changes, and urgent releases that do not change the native binary.

OTA does not replace native releases. A change to native code, permissions, entitlements, linked native modules, or the React Native runtime still requires a new store build. The OTA service must also match each update to a compatible binary version.

The OTA update flow

A store build contains the native application, the React Native runtime, and an embedded JavaScript bundle. The embedded bundle lets the app start before it has downloaded anything from an OTA service.

Once the app is installed, the update flow usually looks like this:

  1. The OTA SDK sends the platform, app version, deployment, and installed release identifier to the update service.
  2. The service returns a release only when it is compatible with that native binary and deployment.
  3. The SDK downloads the payload, verifies it, and stores it on the device.
  4. The app loads the new bundle according to the selected install mode, often on the next restart or resume.
  5. If startup or installation fails, a rollback policy can return the app to a working bundle.

An OTA release can only use native APIs already present in the installed binary. It cannot add native capabilities to an app that users have already installed.

What an OTA release can contain

A React Native OTA release commonly contains a JavaScript bundle, source-map metadata, images, fonts, and other files packaged with the bundle. The exact payload depends on the bundler and the OTA provider.

Updates that require a new native dependency, an iOS entitlement, an Android permission, or a change to native startup code belong in a new IPA, APK, or AAB. Teams normally use target binary versions or runtime versions to prevent an incompatible OTA release from reaching the wrong app build.

Full bundles and diff updates

A full-bundle OTA release sends the complete JavaScript bundle and its packaged assets. This is simple, but a one-line fix can still make a device download several megabytes.

A diff update compares the new release with a compatible bundle already present on the device. The service sends a patch for changed bytes or files and reuses everything else. Smaller payloads reduce mobile data use, CDN egress, and the time spent downloading an update.

Diff delivery needs a known baseline. If the server cannot identify a compatible base bundle, the client must download a full payload or skip the update.

Why the first OTA baseline affects payload size

Some patch systems create their baseline only after the first OTA bundle has reached the device:

text
Native app from the store
  -> first OTA: full bundle
  -> later OTA releases: patches

This leaves the first update after every native release as a full download. That first update is often a hotfix published while a new store version is still reaching a large share of users.

Revopush can create the baseline from the native artifact before the first OTA:

text
IPA / APK / AAB base release
  -> first OTA: compatible diff
  -> later OTA releases: compatible diffs

The revopush release-native command processes the JavaScript bundle and assets already shipped inside an IPA, APK, or AAB. Revopush can then calculate the first OTA against files that are already on users' devices. The device does not need a full OTA bootstrap release first.

Read the Revopush base release documentation for the current commands and supported artifacts.

What diff updates change in production

Payload reduction depends on the original bundle and the files changed in a release. In one production Revopush release, the full OTA package was 18.7 MiB and the generated JavaScript patches ranged from 117.26 KiB to 611.49 KiB.

Those figures are one measured release, not a fixed reduction for every app. They show why the baseline matters: the payload tracks the change instead of repeating the full bundle size. See the React Native OTA binary diff case study for the measurements and release flow.

Choosing a React Native OTA provider

Teams usually choose between a managed CodePush-compatible service, a self-hosted OTA stack, or the Expo Updates model. Compare the migration work, first-release diff behavior, native version support, analytics, security controls, and the cost of both traffic and operations.

The React Native CodePush alternatives comparison covers Revopush, Stallion, Hot Updater, Expo Updates, AppZung, Codemagic CodePush, and the archived standalone CodePush Server.

If you are evaluating a managed service, review the Revopush React Native OTA platform, its pricing, and the SDK setup before testing a release.

Migrating from App Center CodePush

Microsoft retired App Center CodePush on March 31, 2025. An existing React Native app needs a maintained client, new service endpoints and deployment keys, migrated release workflows, and a tested production rollout.

Revopush keeps CodePush concepts such as applications, deployments, release-react, staged rollouts, promotion, and rollback. Follow the App Center CodePush migration guide for the client and CLI steps.

React Native New Architecture

New Architecture apps need an OTA client that supports current React Native host and native integration patterns. Revopush supports React Native 0.76 and later with both the New and Old Architecture. The setup differs for React Native 0.76-0.82 and 0.83+, so native instructions should match the installed React Native version.

See CodePush for React Native with New Architecture support and the current Revopush SDK user guide.

OTA updates in Expo apps

Expo apps can use Expo Updates or integrate another OTA provider through native configuration. Revopush uses @revopush/react-native-code-push with an Expo config plugin. Because the integration contains native configuration, it requires a development or production build and does not run in Expo Go.

The Expo CodePush and Revopush guide covers installation, the config plugin, base releases, and release-expo. You can also compare the two delivery models in Revopush vs Expo Updates.

OTA updates and Server-Driven UI

OTA and Server-Driven UI solve different release problems. OTA downloads compiled JavaScript and assets. Server-Driven UI sends a schema or configuration that an existing native or JavaScript renderer interprets at runtime.

OTA is suitable for application logic, fixes, and screens that should continue to work offline. Server-Driven UI is useful when a team changes content or supported layouts frequently from a backend. Many apps use both, with OTA for code and SDUI for selected dynamic surfaces.

Read OTA vs Server-Driven UI in React Native for the tradeoffs and example use cases.

OTA security

An OTA channel can change production application behavior, so release access should be treated like access to an app-signing or deployment system. Use separate deployments, least-privilege access, protected CI credentials, code signing where supported, staged rollouts, and rollback procedures.

Teams also need to keep native and OTA compatibility rules explicit. An update should be rejected when the installed binary does not provide the native APIs expected by its JavaScript bundle.

Review security practices for React Native OTA updates and the Revopush Security Statement.

OTA analytics

A successful upload does not show whether devices downloaded or installed the release. OTA analytics should distinguish update checks, downloads, successful installs, installation errors, active release adoption, and rollback events.

Release-level data helps a team decide whether to expand a staged rollout, pause it, or roll back. See React Native OTA analytics with Revopush.

OTA updates in CI/CD

A repeatable pipeline builds the bundle from a known commit and creates the matching source maps. It publishes first to a non-production deployment with a protected credential, then promotes the same tested release to production.

Revopush supports CodePush-style CLI automation. Use the relevant guide for GitHub Actions, Bitrise, or CircleCI.

Continue with Revopush