Life after App Center: choosing an OTA path as CodePush sunsets
· 4 min read · Amrith Vengalath
- React Native
- CodePush
- OTA
- Expo
If your React Native app shipped JS fixes over the air through CodePush, you've probably seen the notice: App Center is being retired, and CodePush as a hosted service goes with it. The deadline is real and it's this year. For apps that lean on OTA for hotfixes - which is a lot of us - this isn't optional housekeeping. You need a plan before the service stops.
I went through this decision for a production app. Here's the honest lay of the land.
First, be clear about what you're losing
CodePush did two things: a client SDK in your app that checks for and applies JS bundle updates, and a hosted backend that stored bundles, handled staged rollouts, and tracked deployments. The service going away takes the backend with it. So your options are really "what replaces the backend, and what client do I use."
The options, roughly
Expo Updates (EAS Update). If you're on or willing to move toward the Expo tooling (which works in bare React Native projects now, not just managed ones), EAS Update is the most direct spiritual successor - hosted, supports channels and staged rollouts, integrates with EAS Build. For most teams that just want OTA to keep working with minimal fuss, this is the path of least resistance. The catch is it pulls you into the Expo ecosystem and its pricing, which may or may not fit.
A self-hosted / open-source CodePush server. The community saw this coming and there are open-source CodePush-compatible servers. You run the backend yourself, keep something close to the CodePush client and workflow. This appeals if you want control, have somewhere to host it, and don't want a per-seat or usage bill. The cost moves from a subscription to your own ops time.
Roll your own minimal OTA. OTA isn't magic - at its core it's "download a JS bundle, check it's compatible with the binary, swap it in on next launch, roll back if it crashes." For a team with specific needs and the appetite, a minimal in-house solution is feasible. I'd be cautious here: the easy 80% (download and apply) hides the important 20% (staged rollout, signature verification, safe rollback), and that's exactly the part you don't want to get wrong on your whole user base.
How to actually decide
The questions I worked through:
- How much do you depend on OTA? If it's load-bearing for hotfixes, treat this as a priority migration, not a someday task. If you barely used it, this might be the moment to simplify and lean on faster store review instead.
- Are you already near the Expo ecosystem? If yes, EAS Update is low-friction. If you've deliberately stayed bare and want to keep it that way, a self-hosted server fits better.
- Subscription cost vs ops cost. Hosted is money; self-hosted is maintenance. Neither is free. Pick the one your team is better set up to absorb.
- What's the migration effort in the app itself? Swapping the client SDK and the release pipeline is real work and testing. Budget for it.
Don't forget the safety features
Whatever you choose, the non-negotiables from the CodePush era still apply: staged rollout to a small percentage first, automatic rollback if an update crashes on startup, and binary-version targeting so you never push JS to an incompatible native build. If a replacement makes those hard, that's a strike against it. The safety discipline matters more than which logo is on the dashboard.
My take
For most teams, moving to EAS Update is the pragmatic choice - it's maintained, it has the rollout and rollback features, and it's the closest thing to "CodePush but it still exists." Teams with strong reasons to stay independent and the ops capacity should look hard at a self-hosted CodePush-compatible server. Rolling your own is for the minority with very specific constraints and a healthy respect for the rollback edge cases.
The one thing not to do is wait. The service has a date, and discovering your hotfix channel is dead the day you need a hotfix is the worst possible time to start this migration. Pick a path now, migrate while there's no fire, and test it before you're relying on it.