Updates and rollouts

What is an over-the-air update for mobile apps

An over-the-air update delivers new code to a mobile app over the network: a new JavaScript bundle, not a new binary, within limits set by the app store rules.

10 min read

Quick answer

An over-the-air (OTA) update delivers new code or content to a device over the network, without the user downloading a new version from an app store. For mobile apps built with JavaScript frameworks such as React Native, an OTA update replaces the app's JavaScript bundle and assets, within the limits of App Store Review Guideline 2.5.2. Native code still requires a store release and store review.

What does "over the air" mean?

A one-star review lands at 9:40 on a Friday: "Crashes every time I open order history." The bug is one line of JavaScript, and the fix is ready before lunch. How that fix reaches phones is the question OTA updates answer.

"Over the air" is a radio term. It means the software arrives by network instead of by cable or a trip to a service center. A phone's operating system, a thermostat, a car and an app can all update this way.

The phrase covers three kinds of update with different mechanics, and only one of them applies to mobile apps.

How is an app OTA update different from a firmware OTA update?

Cars and connected devices. The manufacturer pushes new firmware to the device. The update replaces low-level software, often including code that controls hardware, and there is no third-party store in the path.

Phone operating systems. Apple and Google deliver iOS and Android updates the same way. The platform owner controls the whole path.

Mobile apps. Here the developer does not control the platform. Apps are installed and updated through the App Store and Google Play, and each store reviews the app before it goes live. An OTA update for an app works within that system rather than around it: the app binary the store reviewed stays installed and unchanged. What changes is the interpreted code (the JavaScript bundle) and assets that the binary loads at launch.

When a React Native developer says "we shipped an OTA update", they mean a new JavaScript bundle reached users' phones. Native code did not change.

What can an OTA update change in a mobile app?

A React Native app has two layers: a native layer, compiled into the binary and reviewed by the store, and a JavaScript layer that the native layer loads and runs. OTA updates operate on the second layer only.

Can be changed by an OTA updateNeeds a new binary and store release
JavaScript application code: screens, logic, bug fixesNative code and native modules
Styling and layoutNew native dependencies (a camera library, a payments SDK)
Copy and translationsApp permissions (camera, location, notifications)
Images, fonts and other static assets bundled with the JavaScriptThe framework or SDK version
Configuration values read by JavaScriptApp icon, splash screen and other native resources

The split comes from Expo's EAS Update introduction. Every OTA system for React Native has the same boundary, because the runtime sets it, not the vendor. An OTA update fits a JavaScript bug fix or a layout change. It is the wrong tool for anything that adds a native capability.

Are OTA updates allowed by Apple and Google?

Both stores allow OTA updates of interpreted code, with conditions.

Apple. App Store Review Guideline 2.5.2 says apps "may not download, install, or execute code which introduces or changes features or functionality of the app". The Apple Developer Program License Agreement, in section 3.3.2, allows interpreted code to be downloaded to an app as long as it "does not change the primary purpose" of the app. A publicly filed copy of the DPLA shows the wording; the current version requires a developer sign-in. Read together, the two rules permit fixing the JavaScript your reviewed app already runs. Turning the app into something the reviewer did not see is not allowed.

Google. The Play Device and Network Abuse policy says an app "may not download executable code (such as dex, JAR, .so files) from a source other than Google Play", and then states that the restriction "does not apply to code that runs in a virtual machine or an interpreter". JavaScript in a React Native app is interpreted code under that exception.

Neither store treats an OTA update as a way to skip review. The binary was reviewed; the update changes the JavaScript inside it, and the update itself has to stay within the same guidelines.

How does an OTA update work in a React Native app?

Details vary by vendor. This section follows the Expo Updates protocol, which is public and which any server can implement.

Runtime version. Every build carries a string that describes its native layer. Every update declares which runtime version it targets. The client only accepts updates whose runtime version matches its own exactly. Runtime versions are the mechanism that stops a JavaScript bundle from being loaded by a native layer that lacks the modules it calls.

Channel. A channel is a name baked into the build at build time, such as "production" or "staging", that tells the server which stream of updates this build should receive. Two builds with identical native code can be on different channels so that testers see an update before the public does, as How EAS Update works describes.

Manifest. When the app checks for an update, it sends its platform, runtime version and channel. The server responds with a manifest: a JSON document that names the update, its creation time, the entry-point JavaScript file, and every asset the update needs, each with a SHA-256 hash. The client downloads any asset it does not already have, verifies the hashes, and stores the update locally.

Launch. By default the client checks on cold launch, downloads a newer update in the background, and runs it on the next launch. If the download finishes within a configurable timeout, it runs immediately.

Rollback. A rollback is either a republish of an earlier update (so clients fetch the known-good bundle as if it were new) or a directive telling clients to run the bundle embedded in the binary. The Expo Updates protocol defines a directive type for the second case, rollBackToEmbedded.

Code signing. The manifest can be signed with a key the developer controls, and the client verifies the signature before it downloads anything. Because asset hashes are in the manifest, signing the manifest covers the assets too.

How do OTA updates relate to hotfixes, staged rollouts and feature flags?

Hotfix. A small, urgent fix shipped outside the normal release cadence. An OTA update can deliver a JavaScript hotfix. Only a store release can deliver a native one.

Staged rollout. Releasing to a percentage of users first, then widening. Apple's phased release goes from 1% on day one to 100% on day seven; Google Play lets you pick a percentage and halt. OTA services offer the same control for the JavaScript layer, with the percentage adjustable in minutes.

Feature flag. A server-controlled switch that turns a code path on or off. A flag can hide a broken feature without shipping code; an OTA update can repair it. Teams use both.

What happened to CodePush?

For years the best-known OTA service for React Native was Microsoft's CodePush, part of Visual Studio App Center. Microsoft retired App Center on 31 March 2025. Microsoft published a standalone CodePush server so that teams could keep running the same client against their own infrastructure; the repository is archived, and Microsoft states it "will not provide support services for it". The other paths are a hosted service (EAS Update is one), or the open-source expo-updates client pointed at a self-hosted server that implements the protocol above. Expo's What to do without CodePush lays out the options, and the CodePush migration guide covers the conceptual differences.

What are the key facts about OTA updates?

QuestionAnswerSource
What layer does an app OTA update change?The JavaScript bundle and its assetsExpo docs
Does it change native code?No. Native changes need a store releaseExpo docs
Apple ruleGuideline 2.5.2 and DPLA 3.3.2Apple
Google ruleInterpreter exception in the Device and Network Abuse policyGoogle
How does the client avoid incompatible updates?Exact runtime version matchExpo docs
When did CodePush shut down?With App Center, 31 March 2025Microsoft

Where Expo fits

EAS Update is Expo's hosted implementation of the protocol described above. It serves updates to any app that includes the expo-updates library, including existing React Native projects that were not started with Expo. Publishing is one command, and the update reaches builds on the named channel with a matching runtime version:

Rollouts by percentage (eas update --rollout-percentage=10) and rollbacks (eas update:rollback) are built in. Since SDK 55, EAS Update can ship a patch against the previous bundle instead of the whole bundle; in Expo's testing, bundle diffing produced "approximately 75% smaller downloads".

Limitations

EAS Update changes the JavaScript layer only; native changes need a new build through the store, and every update has to stay within App Store Review Guideline 2.5.2. The --environment flag is required from SDK 55, per the getting started guide. By default the app checks on cold launch; the Updates API lets you check in the foreground or background instead. There is no built-in mandatory-update flag. The free plan includes 1,000 monthly active update users, with 3,000 on Starter, 50,000 on Production and 1,000,000 on Enterprise before usage-based pricing applies; end-to-end code signing is on the Production and Enterprise plans, according to Expo pricing.

Next step

If your app is built with React Native, the EAS Update introduction has a table of what you can and cannot ship as an update, and links to the getting-started guide.

Verified on 12 September 2026.

Keep reading

Frequently Asked Questions