All posts
3 min readBy BetterCodePush

The React Native upgrade treadmill — and what OTA can and can't do about it

Google and Apple set submission requirements, while React Native evolves underneath your app. Where an update channel actually relieves the pressure — and where it cannot.

React NativeUpgradesRelease EngineeringOTA

Talk to React Native teams about what actually burns their time and it's rarely feature work. It's the treadmill: an upgrade lands, you stabilize, you ship — and within a quarter another deadline forces the next one. One team described their year as "upgrade, stabilize, get forced to upgrade again," and the description resonates because the cadence isn't self-imposed. It comes from three external clocks that don't care about your roadmap.

The three clocks

  • Google's API-level floor. Google Play publishes an annual target API requirement for new apps and updates. The current requirementspecifies Android 16 (API 36) from August 31, 2026 for standard mobile apps. Raising a target can surface behavior and dependency changes, so treat it as a native release project rather than a version-string edit.
  • Apple's SDK requirement. Apple changes its submission requirement on its own schedule. As of April 28, 2026, its submission guidancerequires iOS and iPadOS apps to use the iOS 26 SDK or later. That can mean updating Xcode, CI images, and native dependencies.
  • React Native itself. Releases can change the native integration surface. React Native enabled the New Architecture by default in 0.76, and 0.82 became the first release that runs entirely on it. Plan upgrades against your dependencies and test matrix instead of assuming an OTA layer can smooth over native compatibility work.

Why the treadmill hurts more than the sum of its parts

The compounding cost is what an upgrade does to your release pipeline: during an upgrade, the pipeline is occupied. There's a migration branch, a frozen main, a "let's not ship anything else until this stabilizes" posture. If a product bug surfaces mid-migration, you face an ugly choice — ship a fix through a half-migrated pipeline, or make users wait until the dust settles. Teams under deadline pressure reliably pick "wait," and product quality quietly pays for infrastructure work.

What OTA genuinely changes

Let's be precise, because vendors oversell this. An update channel does not do your upgrades. Every one of those three clocks demands a native build; no JavaScript delivery mechanism touches that, and the boundary is hard. What OTA changes is the coupling:

  • Compatible fixes stop competing with migrations. The 1.8.0 binary in the store can keep receiving compatible JavaScript fixes while the 1.9.0 migration branch takes its time. Native fixes and runtime-incompatible bundles still need a new binary.
  • The fleet's long tail stays serviceable. After any release, a slice of users lingers on old binaries for weeks. With per-app-version targeting, you can still ship a critical JS fix to the 1.7.x stragglers without resurrecting an old pipeline.
  • Upgrade-day risk shrinks. The scariest moment of an RN upgrade is the first store release on the new runtime. With an OTA channel and staged rollouts, the JS regressions that slip through can be fixed without becoming emergency store submissions on top of an already stressful week. One caveat to respect: the first build on a new runtime is a new compatibility world, so rebuild updates against it rather than recycling bundles from the old toolchain.

The honest summary

Platform requirements and ecosystem changes are permanent features of mobile development. What you can refuse is their tax on everything else. Decouple your compatible fix path from your upgrade path, and the upgrade becomes a project instead of a hostage situation. That decoupling is, honestly, a bigger quality-of-life win than the "ship features faster" pitch OTA usually gets sold on.

Ship your first update

Create an organization and deploy an over-the-air update in minutes. No billing setup during the beta.

Start with BetterCodePush