Rheo CLI is live. Let your agents be your growth engine.

Learn more
React Native OTA migration from CodePush to EAS Update
Engineering

React Native OTA after CodePush: EAS Update, policy, and what growth teams still need

CodePush retirement, EAS Update migration, App Store policy, and what OTA cannot replace for growth teams (journey experimentation).

Microsoft retired App Center CodePush in March 2025. Teams that relied on it for JavaScript hotfixes now route through Expo Application Services (EAS) Update, custom OTA pipelines, or a return to store releases. That migration is necessary engineering work. It is also incomplete if your growth team still equates "over the air" with "we can test onboarding tomorrow."

OTA updates ship code. Remote flow platforms ship journey definitions. The distinction matters for subscription apps where flow iteration speed often beats bugfix velocity. This guide covers CodePush retirement fallout, EAS Update as the default CodePush alternative for React Native, store policy guardrails, and what growth teams still need after OTA is solved.

What CodePush retirement changed

CodePush let React Native teams push JavaScript bundle updates without a full App Store review. Microsoft bundled it with App Center, which also shut down. If you have not migrated, you are already on borrowed time.

CapabilityCodePush (retired)Typical replacement
JS bundle OTAYesEAS Update, custom CodePush fork
Native module changesNoStore release required
RollbackSupportedEAS channels, staged rollout
DashboardApp Center (gone)Expo dashboard or self-hosted
PricingWas bundledExpo plans or infra cost

Teams on bare React Native without Expo often evaluate:

  • EAS Update with Expo prebuild or a brownfield integration
  • Self-hosted solutions (for example, @bravemobile/react-native-code-push community forks)
  • No OTA: return to weekly or biweekly store releases

None of these options replace funnel experimentation infrastructure. They replace one delivery channel for JavaScript.

EAS Update as the default migration path

For many Expo and React Native teams, EAS Update is the most documented CodePush alternative. The mental model is similar: publish a bundle, assign it to a channel, clients check for updates on launch or resume.

Migration checklist

StepAction
1Audit current CodePush keys, deployment names, and rollback scripts
2Map deployment names to EAS channels (production, staging, beta)
3Add expo-updates and configure app.json / app.config.js
4Wire CI to eas update --branch production on merge
5Test rollback by promoting a previous update ID
6Remove App Center SDK and dead keys from native projects
7Document who can publish and which channel maps to prod

Runtime behavior teams forget

EAS Update checks are asynchronous. Users on a cold start may see the previous bundle for one session before the new bundle applies. Funnel changes that depend on "instant publish" need a different layer (remote flow manifests resolve on each session).

OTA also cannot change:

  • Native dependencies (RevenueCat SDK bump, new camera permission string)
  • App icons, splash screens, entitlements
  • Binary-linked paywall SDK major versions

Growth hypotheses that only touch JavaScript UI inside your existing navigation may fit OTA. Hypotheses that restructure onboarding order across five screens with new branch types often fit a flow platform better than bundle diffs.

App Store and Play policy: what OTA may ship

Apple and Google allow JavaScript updates within limits. Policies evolve; verify current guidelines before you publish. The practical rules teams cite:

Allowed via OTA (typically)Requires store review (typically)
Bug fixes in JSNew native APIs or permissions
Copy and styling in existing screensChanging app primary purpose
Remote config driven UI in existing viewsBinary changes to IAP implementation
A/B flags that toggle existing componentsAdding new subscription products without store metadata

Apple Guideline 3.3.2 (interpreted in release notes and reviewer feedback) expects that OTA does not turn your app into a different product. Google Play has parallel language about deceptive behavior and mandatory update mechanisms.

Risk pattern: shipping a paywall redesign via OTA that changes pricing presentation without updating store listing metadata. Billing and merchandising teams should review OTA diffs the same way they review store screenshots.

Safer pattern: OTA for bugfixes and minor UI; remote flows for journey structure; store release for native billing SDK upgrades and new SKUs.

What OTA does well vs what growth teams need

OTA solves engineering velocity for the JavaScript layer. Growth teams need experiment velocity across the funnel.

NeedOTA (EAS Update)Remote flows (Rheo)
Fix crash in checkout JSStrong fitNot the right tool
Change headline on onboarding screen 2Possible (needs release cadence)Publish in seconds
Test 4-screen vs 7-screen onboardingAwkward (feature flags in code)Native experiment assignment
Branch on campaign / ATT / localeCustom code per branchDashboard rules
Step-level funnel analyticsInstrument yourselfBuilt per screen
Paywall presentationYour billing SDK UIRevenueCat / Superwall node in flow

Rheo does not replace EAS Update. Rheo does not ship your React Native bundle. Rheo orchestrates journeys rendered by the SDK while your app binary and OTA pipeline stay unchanged.

Combined stack diagram

Store release (binary)
    └── EAS Update (JS fixes, minor toggles)
            └── Rheo SDK (onboarding, lifecycle flows)
                    └── RevenueCat / Superwall (paywall UI + purchase)

Engineering owns the bottom of the stack. Growth owns the middle. Billing integrations own paywall presentation at the moment of purchase.

Policy-aware experiment design after CodePush

Once EAS Update is live, resist the urge to route every growth test through bundle publishes.

Problems with funnel-only OTA:

  1. Statistical noise: bundle version and experiment variant confound unless you version carefully
  2. Rollback blast radius: reverting a bad onboarding test also reverts unrelated JS fixes in the same bundle
  3. Review anxiety: teams self-censor journey tests that touch purchase-adjacent screens
  4. Analytics gaps: screen order in code does not automatically produce step funnels

Better split:

Hypothesis typeDelivery
Navigation crash, RN version bumpEAS Update or store
Onboarding order and branchesRemote flow publish
Paywall template and pricingRevenueCat Experiments or Superwall
Cancel survey and win-backRemote flow publish

Document this split in your growth wiki so PMs do not file "OTA request" tickets for copy changes.

Migration timeline template

WeekEngineeringGrowth
1Stand up EAS project, parity test on stagingInventory hardcoded onboarding screens
2Cut over production channel, monitor crash ratesMap first remote flow channel (first_open)
3Remove CodePush SDKRun parity test: remote flow vs legacy path
4Automate CI publishFirst experiment on flow length (not in OTA)

Parallel tracks prevent a common failure mode: OTA migrated in Q3, onboarding experiments still queued for Q4 store releases because nobody owned the flow layer.

CodePush alternative React Native: decision tree

Use this when evaluating tools:

  1. Do you only need JS hotfixes? → EAS Update (or maintained fork)
  2. Do you need non-engineers to change onboarding? → Add remote flows; keep EAS for code
  3. Do you need paywall A/B tests? → RevenueCat Experiments or Superwall; not OTA alone
  4. Do you need native module changes? → Store release; plan ahead

Searching for a codepush alternative react native leads to EAS Update articles. Searching for onboarding experiment velocity leads to flow platforms. Both searches are valid. They solve different problems.

Metrics after migration

Track OTA health separately from funnel health.

MetricOTA dashboardFlow analytics
Update adoption rateEASN/A
Crash-free sessions post-updateSentry + EASN/A
Onboarding completionYour product analyticsRheo step funnel
Trial start rateRevenueCatRheo + RC events
Time to publish a funnel changeN/AMinutes

If time-to-publish for onboarding changes is still measured in days after EAS migration, you fixed deployment but not experimentation.

Common mistakes

Mistake 1: One channel for everything. Production OTA channel carries experiments and hotfixes. Split channels or use remote flows for tests.

Mistake 2: Assuming OTA replaces store review for billing. New products and major IAP changes still go through store processes.

Mistake 3: Ignoring first-session lag. Users may not pick up the bundle until session two. Time-sensitive campaigns need manifest-based flows or forced update prompts (use sparingly).

Mistake 4: No owner for journey layer. Engineering completes EAS migration; growth still files app release tickets for copy tests.

Summary

CodePush retirement pushed React Native teams toward EAS Update and similar OTA paths. That is the right fix for JavaScript delivery. It is not the full fix for subscription growth loops that depend on onboarding, permissions, and lifecycle flows.

Use OTA for code. Use billing integrations for paywall UI. Use remote flows for journey experimentation at the speed of paid acquisition. The stack is complementary when each layer has a clear owner.

Start for free and pair Rheo journey experiments with your EAS Update pipeline.