On March 31, 2025, Microsoft retired Visual Studio App Center, and CodePush — the service that defined over-the-air updates for a decade — went with it. If your release process still has a code-push release-react step in it, that step has been pointing at a tombstone for over a year.

We build one of the tools on this map (Patch, the native-Swift one) — so read accordingly.

What CodePush proved

CodePush's decade established that OTA code updates are a legitimate, mainstream practice on iOS and Android. Ship the fix as an interpreted payload (JavaScript, in its case), let the app pick it up at next launch, keep the signed binary untouched. Apple's rules conditionally permit this pattern — the conditions bind you, the developer, not the vendor (the rules in detail) — and a large share of production React Native apps ran on it. The pattern outlived the product; every tool below is the same architecture with a different payload (how it works under the hood).

The 2026 map

React Native: from CodePush to EAS Update

Microsoft's own retirement notice pointed at exactly one path: the open-sourced standalone code-push-server for self-hosters — since archived upstream, with community forks carrying it on. Viable if you have the ops appetite, increasingly lonely if you don't. The ecosystem's consensus destination is EAS Update: Expo published its own migration guide, and in most ways it's an upgrade — channels, staged rollouts, code signing, an open protocol, first-class Expo integration.

Flutter: Shorebird

Founded by Flutter's creator, Eric Seidel, Shorebird brought code push to Dart's AOT world: unchanged code runs at full native speed, changed code runs in an interpreter, patches are diffs. It's the established answer in its ecosystem.

Native Swift / SwiftUI: Patch

Native iOS briefly had OTA — JSPatch, Rollout.io — and Apple purged it in 2017, because those tools let downloaded code reach into the Objective-C runtime and redefine reviewed behavior. The gap since then was real: no JS bundle, no Dart VM, nothing to update. Patch closes it with the opposite architecture. You write ordinary Swift; the CLI compiles your changed code to WebAssembly; the on-device SDK (public source) runs it in WasmKit, a WASM interpreter written in Swift — and a patch can only call the host functions the shipped, reviewed binary exposes. There is no path to the ObjC runtime, or to APIs your binary didn't already use. Code that touches OS APIs stays native, detected automatically, with an automatic fallback chain to the code your binary shipped with; hash verification, staged rollouts, channels, and one-command rollback are built in. Pure-logic patches ship at kilobytes; patches that pull in heavier library surface ship larger. It's live today: brew install patch-release/tap/patchcli, free tier, iOS 16+, about ten minutes from install to first patch on a device.

Whichever you pick: the compliance fine print

OTA updates an interpreted layer, never the native shell — new native dependencies still mean a store release. And Apple's interpreted-code conditions bind you regardless of vendor; as 2017 proved, the line between permitted and purged is Apple's to draw. Any tool selling "Apple-approved" is overselling. What a good tool gives you is the mechanism plus the operational safety net — verification, rollout controls, rollback — to use it responsibly.

Your stackToolPayloadStatus in 2026
React NativeEAS UpdateJS bundle / Hermes bytecodemainstream default
React Native (self-host)code-push-serverJS bundlearchived upstream; community forks
FlutterShorebirdDart patchestablished
Native Swift / SwiftUIPatchWASM modulelive, the new entrant
Any (UI-config only)server-driven UIJSONnot code updates

When did CodePush shut down?

March 31, 2025 — Microsoft retired Visual Studio App Center and the hosted CodePush service with it. The client SDK and server code were open-sourced for self-hosting (and the server repo has since been archived).

What replaced CodePush?

For React Native, most teams migrated to Expo's EAS Update; self-hosters run forks of the open-sourced code-push-server. Flutter teams use Shorebird. Native Swift apps — which CodePush never covered — use Patch.

If you're migrating (or starting fresh)

The questions that actually matter, in order:

  1. Inventory the dependency. How many releases shipped through OTA last year? What's your median time-to-fix without it? That tells you how much you depended on it — or what you've been missing if you're native and never had the lane.

  2. Map your update boundary. What share of your bugs lives in the updatable layer — JS, Dart, or (for native apps) the logic/view-model/SwiftUI slice within the patchable boundary vs. raw OS-API code? The boundary, not the vendor, determines what OTA can ever do for you.

  3. Demand the safety net. Staged rollout percentages, instant rollback, integrity verification, and a fallback path on-device. CodePush-era muscle memory sometimes skips these; none are optional.

  4. Write the compliance paragraph once. One honest paragraph on what your mechanism does and how it meets the interpreted-code conditions — wherever you land, have it ready before App Review asks, not after.

CodePush's retirement didn't shrink the category; it reorganized it — and extended it to the one ecosystem that never had it. If you ship React Native, your path is well-paved. If you ship Flutter, likewise. And if you ship native Swift, you now have a lane on the map: see the CodePush alternative for native Swift iOS.


Related: The iOS hotfix playbook · Feature flags vs OTA code updates · Compiling Swift to WebAssembly