How over-the-air updates actually work in React Native, the bundle lifecycle, what changed with the New Architecture, and how to choose the right platform after CodePush.
Anything that requires a `pod install` or Gradle change still needs an App Store release.
Every team running on hosted CodePush has had to migrate by now.
These stages are build, upload, CDN, device check, and apply. Knowing each one is how you debug production failures.
If you're on RN 0.76+ and your OTA succeeds but doesn't reload, you're hitting this issue.
This saves on bandwidth, but only if your platform actually supports diffing.
This permission is for JavaScript and assets. The "Apple doesn't allow OTA" myth has been wrong for a decade.
Over-the-air updates let you change the JavaScript bundle and assets running on a user's device without going through the App Store or Play Store review process. That's the entire idea, and almost every interesting question about OTA comes down to what counts as "JavaScript and assets."
Objective-C, Swift, Kotlin, Java, and all your linked native modules are compiled into a binary, signed, and shipped through Apple or Google. They are frozen the moment the build leaves CI.
Changing even one line of native code requires a new binary, a new submission, and a 24-hour to 7-day review window.
Metro takes all your JavaScript and produces main.jsbundle on iOS and index.android.bundle on Android. This payload is what OTA replaces at runtime.
The native shell has no idea this is happening. From its perspective, it's still loading a bundle from disk and handing it to Hermes.
Almost every OTA bug traces back to confusion about this boundary. Let's draw it precisely.
require(), fonts, JSON filesPodfile or build.gradleInfo.plist, manifest permissions, app icons, launch screensKnowing what happens at each one is the difference between deploying confidently and shipping mystery failures.
Metro produces main.jsbundle and assets. With Hermes, the bundle becomes pre-compiled bytecode.
CLI uploads to your OTA platform with metadata: target binary version, deployment key, release notes, optional rollout percentage.
Platform pushes the bundle to a CDN. HTTP/3 and edge caching minimize time-to-first-byte from the user's location.
On launch or foreground, the SDK queries the platform: "I'm version X, deployment Y, current hash Z. Anything newer?"
SDK downloads, verifies hash and signature, writes to disk, and either reloads immediately or waits for next launch.
Patch updates beat full bundles by an order of magnitude. End-to-end deployment in seconds, not days.
The output of npx react-native bundle is a single JavaScript file containing your entire app: every screen, every utility, and every npm dependency, all transformed and minified.
Every six months someone posts on Hacker News claiming Apple banned OTA updates. They didn't. The actual policy has been stable for nearly a decade.
The code that ties this together is recognizable to anyone who has worked with CodePush because the AppsOnAir SDK is API-compatible by design.
The --rollout 25 flag is the single most important habit. Release to 25% of users, watch error rates for an hour, then bump to 100%, or roll back instantly if anything goes sideways.
With Microsoft App Center retired, every team has had to migrate. Here's an honest comparison of where teams are landing.
Thousands of React Native teams had years of muscle memory built around the CodePush CLI, deployment-key model, and SDK API surface. Migrating away shouldn't mean throwing all of it out.
Every appcenter codepush command has a direct AppsOnAir equivalent. Your CI scripts get a find-and-replace, not a rewrite.
Tested across React Native 0.70 and above, including Bridgeless mode. Documented restart patterns for Bridgeless reload edge cases.
Binary diffing on every release. Typical patches are 5–15% of the full bundle, cutting bandwidth by an order of magnitude.
SOC 2 Type II (in progress) and ISO 27001:2022. Audit-grade deployment logging. The compliance posture your enterprise customers will ask for.
Flat tiers without per-update or per-bandwidth-GB charges. Your bill doesn't compound when your release cadence increases.
OTA distribution, deep linking (AppLink), in-app feedback (AppRemark), and force-update controls (AppSync) under one platform.
If you're coming from App Center CodePush, the path is the simplest of any option. Most teams complete it end-to-end in under a day.
Note your binary versions in flight, deployment keys, current rollout state, and any custom SDK config.
Existing CodePush deployments don't need to stop the day you start AppsOnAir. Run side-by-side and validate.
Most apps need a single import change in App.tsx and a deployment-key update.
Find-and-replace appcenter codepush → appsonair-codepush. The argument shape is the same.
Ship a no-op release to 5% of users, watch error rates and OTA telemetry, then ramp.
No. Microsoft retired Visual Studio App Center, including the hosted CodePush service, on March 31, 2025. The CodePush server source code was open-sourced before retirement, so teams can self-host or migrate to a managed alternative such as AppsOnAir CodePush.
Yes, with conditions. Apple App Store Review Guideline 3.3.2 permits remote JavaScript and asset updates as long as the update doesn't change the app's core purpose or add features that bypass review. Google Play has similar requirements.
Yes. AppsOnAir CodePush supports React Native 0.70 and above, including Bridgeless (New Architecture) mode. Custom restart handling is documented for projects that need to reload the JavaScript runtime after applying an update under Bridgeless.
Full bundle updates ship the entire JavaScript bundle (typically 2–8 MB for a real-world app). Patch updates ship only the diff between the previous and new bundle, typically 50–200 KB. Patch updates dramatically reduce egress costs and download time but require diffing infrastructure on the OTA platform.
Yes. Hermes-compiled bytecode bundles work with all major OTA platforms, including AppsOnAir CodePush. The bundle is platform-specific (iOS Hermes bytecode is different from Android Hermes bytecode), but the OTA flow handles platform targeting automatically. Hermes typically reduces bundle size and improves cold-start performance.
End-to-end is typically 10–30 seconds for the platform side (upload + CDN propagation), plus whatever time it takes for users to launch your app and receive the update. With checkFrequency: 'ON_APP_RESUME', active users typically receive updates within minutes of release.