Why React Native Teams Use OTA Updates
Why React Native teams add OTA delivery, how it changes release cadence, and which compatibility, rollout, verification, and recovery controls make it safe.
Web applications and mobile applications have different delivery boundaries. A web team can deploy new code to infrastructure it controls, and the next request can use that code. A mobile team ships a signed binary through an app store, and that binary remains on each device until the user installs another version.
That difference changes the life of a fix. Correcting a production bug in JavaScript may take minutes, but distributing a new native build also involves compilation, signing, store processing, and user adoption. None of those steps is inherently wrong; they are part of shipping native software. They are simply a larger mechanism than every JavaScript change requires.
Over-the-air updates create a second delivery path. They let an installed React Native application receive compatible JavaScript and assets without producing a new binary for each eligible change. The important word is compatible. OTA delivery does not replace native releases, change what the installed binary can do, or remove a team's obligations to Apple and Google.
Used well, OTA shortens the path for the changes it can safely carry. Used carelessly, it can put JavaScript onto a runtime that was never built to execute it. Understanding that boundary is more important than choosing a provider or running an upload command.
What an OTA update can change
A React Native application contains a native layer and a JavaScript-driven layer. An OTA system replaces the updateable JavaScript bundle and compatible assets; the installed iOS or Android binary, JavaScript engine, native modules, permissions, entitlements, and compiled configuration remain in place.
That updateable layer commonly includes JavaScript or TypeScript logic, UI behavior built from components already present in the binary, copy and configuration represented in the bundle, compatible images or fonts, and JavaScript-only dependency changes. The source file is not the deciding factor: JavaScript can still call a native method an older binary does not contain, and an asset can still require native registration or a loader that was never installed.
The practical test is:
Can the exact production binary already installed on the device execute this bundle and load its assets without relying on a native capability introduced later?
If the answer is yes for a platform, the change may be suitable for that platform's current OTA runtime line. If the answer is no, the team needs a new binary.
The installed binary defines the release boundary
Compatibility question
Does the installed binary already contain every native capability this change needs?
Consider native code, modules, permissions, build configuration, runtime architecture, and platform-specific behavior.
OTA path
Publish JavaScript and compatible assets
Keep the affected platform on the same runtime line and use the normal OTA release controls.
Store path
Build and distribute a new native binary
Bump the affected platform runtime, ship the binary, then publish OTA updates for that new line.
Changing a runtime-version label cannot add native capabilities to an already-installed binary.
What still requires a store release
OTA cannot add compiled code or platform capabilities to an installed application. A new store release is required for changes such as:
- adding, removing, or incompatibly upgrading a native module;
- adding or changing permissions, entitlements, background modes, extensions, intent filters, or manifest declarations;
- upgrading React Native when the upgrade changes native runtime code or interfaces;
- switching the JavaScript engine or React Native architecture;
- changing an Expo config plugin or another build input that alters generated native projects;
- relying on native code or APIs that the installed binary does not expose.
Ambiguous dependency and configuration changes need artifact-level inspection. A package may alter CocoaPods, Gradle, code generation, or native configuration even when the source edit appears in JavaScript or JSON.
Runtime versions record this boundary. Keeping a runtime value says the update remains compatible with that installed native surface. Bumping it separates a new native generation from older installations; it does not upgrade those devices by itself.
The deeper compatibility model is covered in Runtime versions: the compatibility boundary for React Native OTA updates. For ambiguous changes, When an OTA Update Isn't Enough (and You Need a Store Release) provides a platform-by-platform decision framework.
OTA also does not bypass store policy. Apple and Google still define what applications may change after review. Teams remain responsible for using remote delivery within those rules and within the purpose of the reviewed application. An OTA mechanism should not be presented as a way to ship arbitrary native functionality outside store distribution.
Why teams add an OTA delivery path
The most obvious use case is an urgent JavaScript fix. A bad conditional, broken API integration, or navigation regression can affect users even when the native binary is sound. If the correction remains compatible, an OTA release lets the team begin distributing it without first creating another store build.
The same path is useful for less dramatic work. Teams can correct misleading copy, repair a layout, adjust validation, or refine feature behavior without attaching every eligible change to the next native release train. That separation lets native releases focus on native capabilities and store-facing changes while compatible application work follows a lighter delivery path.
OTA can also reduce the delay between publishing a fix and users becoming eligible to run it. It does not guarantee instant adoption. A device may be offline, the application may not launch, the update policy may wait for a later restart, or a rollout may intentionally exclude that installation for now. Store releases also do not always take a fixed amount of time. The useful distinction is control: an OTA system gives the team a delivery mechanism designed for compatible content and can remove a full native build from that particular path.
That mechanism becomes more valuable when paired with gradual exposure. Instead of making a compatible release available to an entire production audience at once, a team can validate it on a test channel, select an early cohort, observe the result, and then expand. OTA is therefore not only a faster transport; it can be part of a more deliberate release process.
Production OTA is more than uploading a bundle
Generating JavaScript and placing it behind a download URL is the beginning of an OTA system, not the end. Production delivery has to answer several different questions.
Is this update compatible?
Runtime compatibility protects installed binaries from bundles that expect a different native interface. The check belongs per platform because an iOS native change does not necessarily change Android, and users can remain on older store binaries for a long time.
Which release track should receive it?
Channels separate release audiences such as internal testing, beta, and production. They describe where an update is published, not whether its JavaScript can run on a device. They also should not be confused with application environments such as development or production API configuration. Release Channels vs Environments: They're Not the Same Thing explains the distinction.
Can the artifact be trusted?
The client should verify what it downloads before making it active. Interrupted transfers, incomplete files, corrupted local data, and unexpected server responses must fail without replacing the current working application. Integrity verification is a prerequisite for activation, not an optional observation after the update starts running.
Who should receive it first?
Staged rollout limits initial exposure, while targeting narrows eligibility to a deliberate group such as internal users or a product cohort. Those controls solve different problems and should compose predictably. Stable device assignment also matters: repeatedly redrawing a random audience on every update check turns a ten-percent rollout into a moving population rather than an observable cohort.
The complete relationship among publishing, targeting, rollout percentage, fallthrough, and recovery is described in How staged rollouts, targeting, and rollback fit together.
What happens when the release is unhealthy?
Server-side rollback can stop sending a problematic release and direct devices toward an earlier compatible target. Device-side recovery addresses a different case: an installation has already adopted an update and cannot start reliably enough to receive the next instruction. A useful OTA design needs a known-good local state and a recovery path that does not depend entirely on the broken release behaving correctly.
Recovery has limits. If failure occurs before the OTA runtime initializes, JavaScript-level health reporting may not observe it. Native crash reporting and startup diagnostics remain necessary. OTA rollback complements observability; it does not replace it.
Can delivery be efficient without becoming fragile?
Downloading a complete bundle for a small source change can transfer much more data than the change requires. Patch delivery can reduce that transfer when a device has a suitable starting state. But a patch has prerequisites, and real fleets contain devices on different release histories.
A robust design treats the patch as an optimization and keeps a complete verified update available when the smaller path cannot be used safely. Why Bundle Drop Combines Patch Delivery with Full-Bundle Reliability examines that tradeoff in detail.
Can the team explain what happened?
Operations need to identify which bundle is running, which runtime and channel it belongs to, whether another update is staged, and why a device did or did not qualify. Release hashes, source maps, update events, and application-specific health signals make rollout decisions evidence-based. Without that context, a release can be technically reversible but operationally difficult to diagnose.
A simple production release flow
A provider-neutral release process can be described without relying on a particular dashboard or command:
A controlled OTA release flow
1 · Prepare
Create an update for a known native runtime
Bundle JavaScript and compatible assets without assuming native capabilities that the installed binary does not contain.
2 · Verify
Publish to a test channel and exercise real release builds
Check startup, critical flows, bundle identity, and platform-specific behavior before production exposure.
3 · Release
Begin with a limited eligible audience
Use a staged percentage or deliberate target while keeping the runtime and channel boundaries explicit.
4 · Observe
Evaluate adoption, startup health, crashes, and product signals
A published update is not complete merely because an artifact was uploaded or downloaded.
Healthy
Expand the rollout deliberately
Increase exposure while the agreed health signals remain within their expected bounds.
Unhealthy
Pause, stop, or roll back
Limit further exposure and move affected installations toward a known-good compatible bundle.
- Classify the change. Confirm that the JavaScript and assets are compatible with the installed runtime on each platform. Create a new native build first if they are not.
- Build one identifiable artifact. Produce the update and preserve its identity so testing, rollout, observability, and rollback refer to the same content.
- Publish to a test track. Use an internal, QA, or staging channel that is exercised by real release binaries rather than only a development server.
- Verify the complete path. Check download, validation, activation timing, cold startup, application behavior, and recovery on representative iOS and Android builds.
- Begin controlled production exposure. Release to a limited percentage or well-understood cohort. Define stop conditions before the rollout begins.
- Observe adoption and health. Watch update failures, startup behavior, crash reports, and product-specific signals. Rollout percentage is not the same as adoption because devices check and restart at different times.
- Expand deliberately. Increase exposure when the evidence is healthy. Keep the same artifact rather than rebuilding nominally identical source between stages.
- Pause or roll back when needed. Stop further exposure and return affected installations to a known-good compatible state. Then publish a new artifact for the correction.
This flow is intentionally conservative. OTA reduces distribution friction, but that is a reason to make release controls easier to use—not a reason to skip them.
Where Bundle Drop fits
Disclosure: I am the creator of Bundle Drop.
Bundle Drop is one implementation of this model for Expo and bare React Native applications. For Expo Prebuild and Continuous Native Generation projects, its config plugin adds the native integration during generation or build while preserving the normal Expo development workflow. Teams can continue using their normal EAS Build profiles to create application binaries. EAS Build is a build service: it produces those binaries. The OTA service handles compatible JavaScript and asset updates after a Bundle Drop-enabled binary has been deployed. The Expo integration guide documents that boundary and the rebuild cases.
The release side includes channels, staged rollout, optional audience targeting, server-side rollback, and on-device recovery for unhealthy update candidates that reach early SDK initialization. Patch-sized delivery is used when applicable, while a verified full bundle remains available as the fallback when the patch path cannot be used safely.
Bundle Drop's plans are not priced by monthly active users. That is a product decision rather than a technical property of OTA, and the reasoning is set out separately in Why We Don't Price by Monthly Active Users.
This section is necessarily shorter than an integration guide. Operational details live in the documentation for runtime versions, channels, staged rollouts, and rollback. The public React Native package and source repository provides the SDK surface. Teams evaluating any provider should still test the native boundary, failed downloads, incompatible runtimes, staged activation, and recovery behavior in their own release builds.
OTA is a release tool, not a compatibility shortcut
React Native teams use OTA updates because many production changes belong to the JavaScript and asset layer already supported by installed binaries. For those changes, a separate delivery path can shorten the time between a verified fix and device eligibility, avoid unnecessary native builds, and support gradual release and recovery controls.
The value does not come from ignoring the native application. It comes from respecting it. Runtime compatibility defines which devices may receive an update. Channels organize release tracks. Integrity checks protect activation. Staged rollout and targeting control exposure. Observability tells the team what is actually running. Rollback and local recovery provide a way out when evidence shows that a release is unhealthy. Patch delivery can improve efficiency when a dependable full-update path remains available.
Before choosing an OTA provider, teams should be able to explain those rules in their own release process. They should know which changes require a store build, how old binaries remain supported, what makes an artifact eligible, how a rollout is observed, and which known-good state a device can recover to.
OTA is useful because it shortens delivery for compatible changes. Safe operation depends on preserving the compatibility boundary and surrounding that faster path with controlled rollout, verification, and recovery.