Updating Apps Without Re-submitting to the Store: How to Use CodePush in React Native
📋 Table of Contents
- The OTA Update Revolution in 2026
- What Happened to CodePush? The App Center Shutdown
- The 2026 OTA Landscape: Top Alternatives Compared
- EAS Updates: The Modern Standard
- Revopush: The CodePush Successor
- Self-Hosted CodePush Server
- Implementation: EAS Updates Step-by-Step
- OTA Best Practices: Safe Deployments at Scale
- Security: Signing, HTTPS & SSL Pinning
- CI/CD Automation for OTA Updates
- Conclusion: The Future of Mobile Updates
The OTA Update Revolution in 2026
App Store review times of 24–72 hours for iOS and 3–7 days for Google Play are unacceptable when a critical bug is affecting your users. In 2026, Over-The-Air (OTA) updates have become the standard for React Native teams who need to ship fixes, UI tweaks, and feature flags without waiting for store approval.
OTA updates work because React Native apps are essentially JavaScript bundles running on a native shell. If you can replace the JavaScript bundle without touching the native code, you can update your app instantly — no store review, no user action required.
But the OTA landscape changed dramatically in 2025. Microsoft retired Visual Studio App Center on March 31, 2025, shutting down the hosted CodePush service that thousands of teams relied on. The lesson was clear: OTA updates are too critical to depend on a platform where they're not the core product. citeweb_search:10#0
This guide covers what happened to CodePush, the best alternatives in 2026, and how to implement a production-grade OTA update strategy that ships fixes in minutes, not days.
What Happened to CodePush? The App Center Shutdown
React Native CodePush was the original OTA update tool for the framework. Built by Microsoft and hosted on App Center, it let teams push JavaScript updates straight to user devices. For years, it was the default choice for any bare React Native project.
That changed when Microsoft retired Visual Studio App Center on March 31, 2025. The entire platform shut down — dashboard, CLI login, update delivery, everything. Developers could no longer push updates or manage deployments through App Center. Only Analytics and Diagnostics got an extension to June 2026. citeweb_search:10#0
The shutdown hit thousands of teams who relied on CodePush for production releases. Before the shutdown, Microsoft released a standalone CodePush server as open-source software. This server is fully compatible with the existing react-native-code-push client SDK. You deploy it on your own cloud — AWS, Azure, GCP, or any provider — and manage updates yourself.
The trade-off is clear: you keep the familiar CodePush workflow, but you own the hosting, scaling, and maintenance. Microsoft won't accept issues or code changes on the repo, so bug fixes are your responsibility. For teams with strong DevOps skills, self-hosting works well. For everyone else, a managed alternative is the better path forward. citeweb_search:10#0
The 2026 OTA Landscape: Top Alternatives Compared
With CodePush's hosted service gone, three paths dominate the React Native OTA ecosystem in 2026:
| Capability | Self-Hosted CodePush | EAS Updates | Revopush |
|---|---|---|---|
| Migration from CodePush | Familiar model, fully self-hosted | Different runtime and release model | CodePush-compatible SDK |
| Managed Cloud | No | Yes | Yes |
| React Native 0.76+ / New Architecture | No actively maintained path | Yes (expo-updates) | Yes |
| Diff/Patch Updates | No publicly documented | Hermes bytecode diffing | Up to 90% egress reduction |
| Analytics & Team Collaboration | You build and maintain | Expo ecosystem | Built-in admin panel |
| Pricing Model | Infra + storage + CDN + DevOps | Subscription + users + bandwidth | Subscription + $0.03/GB over limit |
| 2026 Recommendation | DevOps-heavy teams only | Default for most teams | Fastest CodePush migration |
Key Insight: EAS Updates is the strongest choice for most teams in 2026. It's actively maintained by Expo, supports both Expo and bare React Native projects, and includes phased rollouts, auto-rollback, and Hermes bytecode diffing as of SDK 55. For teams that want CodePush SDK compatibility without self-hosting, Revopush is the easiest migration path. citeweb_search:10#0
EAS Updates: The Modern Standard
Recommended for Most Teams
EAS Updates (Expo Application Services Updates) is the most robust OTA solution for React Native in 2026. Built and maintained by Expo, it supports both Expo managed workflow and bare React Native projects. It includes features that CodePush never had: Hermes bytecode diffing, fingerprint-based native change detection, and seamless integration with Expo's build and submit pipeline.
Why EAS Updates Leads in 2026
- Hermes Bytecode Diffing: Delivers only the changed bytecode between updates, reducing bundle size by up to 90% and cutting bandwidth costs dramatically citeweb_search:10#7
- Fingerprint Detection: Automatically detects when native code changes and prevents incompatible OTA updates from reaching users citeweb_search:10#2
- Phased Rollouts: Release to 5% of users first, monitor metrics, then ramp to 100% — all from the CLI citeweb_search:10#2
- Auto-Rollback: If an update causes crashes, EAS Updates can automatically revert to the previous stable version
- Channel-Based Deployment: Separate preview, staging, and production channels with different update policies
- Expo Ecosystem Integration: Works seamlessly with EAS Build, EAS Submit, and Expo Router
🟢 EAS Updates Excels When:
- You're starting a new React Native project (Expo or bare)
- You want the most actively maintained OTA platform
- Hermes bytecode diffing and bandwidth optimization matter
- You need fingerprint-based native change detection
- You want integrated build, update, and submit pipelines
- Your team values phased rollouts and automatic rollback
Revopush: The CodePush Successor
Revopush is the managed alternative that maintains direct compatibility with the CodePush SDK. If your team has existing CodePush integrations and wants the fastest migration path without rewriting your update logic, Revopush is purpose-built for this scenario.
Revopush Key Features
- CodePush SDK Compatible: Drop-in replacement for
react-native-code-push— minimal code changes required - React Native 0.76+ Support: Full compatibility with the New Architecture and Bridgeless mode citeweb_search:10#7
- Diff Updates: Up to 90% bandwidth reduction with patch-based delivery citeweb_search:10#7
- Built-in Analytics: Admin panel with deployment metrics, adoption rates, and error tracking
- Managed Infrastructure: No self-hosting required — focus on your app, not your update server
🔴 Revopush Excels When:
- You have an existing CodePush integration to migrate
- You want SDK compatibility without self-hosting
- Your team is on React Native 0.76+ with New Architecture
- You need diff updates for bandwidth optimization
- You want a managed service with built-in analytics
Self-Hosted CodePush Server
Microsoft published the standalone CodePush Server source code before the App Center shutdown. This path keeps the original deployment model alive but moves the entire operational burden to your team.
Self-Hosting Trade-offs
| Factor | Pros | Cons |
|---|---|---|
| Control | Full control over infrastructure, data, and customization | You own uptime, security patches, and scaling |
| Cost | No per-update fees | Hidden costs: servers, CDN, storage, DevOps time |
| Maintenance | Can customize for internal needs | Repository archived by Microsoft — no official support |
| Diff Updates | Possible with custom implementation | No publicly documented diff-update delivery |
🔵 Self-Hosted Excels When:
- You have a dedicated DevOps team with cloud infrastructure expertise
- Data sovereignty requirements mandate self-hosted solutions
- You need deep customization of the update server
- Your update volume is high enough that managed pricing doesn't make sense
Implementation: EAS Updates Step-by-Step
Here's how to implement EAS Updates in a React Native project from scratch. This works for both Expo managed workflow and bare React Native projects.
Step 1: Installation & Configuration
# Install EAS CLI globally
npm install -g eas-cli
# Login to your Expo account
eas login
# Initialize EAS in your project
eas init
# Configure updates in app.json or app.config.js
{
"expo": {
"runtimeVersion": {
"policy": "appVersion"
},
"updates": {
"url": "https://u.expo.dev/your-project-id",
"checkAutomatically": "ON_LOAD"
}
}
}
Step 2: Wrap Your App with expo-updates
import { useEffect, useState } from 'react';
import { View, Text, Button, ActivityIndicator } from 'react-native';
import * as Updates from 'expo-updates';
export default function App() {
const [isUpdating, setIsUpdating] = useState(false);
const [updateAvailable, setUpdateAvailable] = useState(false);
useEffect(() => {
checkForUpdates();
}, []);
const checkForUpdates = async () => {
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
setUpdateAvailable(true);
}
} catch (error) {
console.error('Error checking for updates:', error);
}
};
const downloadAndApplyUpdate = async () => {
setIsUpdating(true);
try {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync(); // Applies update immediately
} catch (error) {
console.error('Error applying update:', error);
setIsUpdating(false);
}
};
if (isUpdating) {
return (
Updating app...
);
}
return (
Your App Content
{updateAvailable && (
)}
);
}
Step 3: Publish an OTA Update
# Publish to preview channel (for internal testing) eas update --channel preview --message "Fix login bug" # After testing, publish to production eas update --channel production --message "Fix login bug v2" # Gradual rollout — start with 10% of users eas update --channel production --message "New checkout flow" --rollout-percentage 10 # Increase rollout after monitoring eas update:edit--rollout-percentage 50 eas update:edit --rollout-percentage 100
Step 4: Automatic Update on App Launch (Silent Updates)
import { useEffect } from 'react';
import * as Updates from 'expo-updates';
export default function App() {
useEffect(() => {
const checkForSilentUpdate = async () => {
try {
// Check silently on app launch
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
// Download in background without blocking UI
await Updates.fetchUpdateAsync();
// Apply on next restart (default behavior)
// Or force immediate reload for critical fixes:
// await Updates.reloadAsync();
}
} catch (error) {
// Silently fail — app works with current bundle
console.log('Update check failed, using current version');
}
};
checkForSilentUpdate();
}, []);
return ;
}
Best Practice: The default behavior (download in background, apply on next cold start) is recommended for most apps. It ensures fast startup times while keeping users on the latest version. Only force immediate reload for critical security fixes or crashes. citeweb_search:10#2
Step 5: Fingerprint-Based Native Change Detection
One of EAS Updates' most powerful features is automatic detection of native code changes. This prevents the #1 cause of OTA failures: shipping a JavaScript update that requires native modules the user's app doesn't have.
# Compare current project against a production build eas fingerprint:compare --build-id# If fingerprints match → safe to ship OTA # If fingerprints differ → native code changed, need new build
name: Deploy to Production
on:
push:
branches: ['main']
jobs:
fingerprint:
name: Check fingerprint
type: fingerprint
environment: production
get_build:
name: Check for existing build
needs: [fingerprint]
type: get-build
params:
fingerprint_hash: ${{ needs.fingerprint.outputs.android_fingerprint_hash }}
profile: production
build:
name: Build (if native changed)
needs: [get_build]
if: ${{ !needs.get_build.outputs.build_id }}
type: build
params:
platform: android
profile: production
update:
name: OTA Update (if native unchanged)
needs: [get_build]
if: ${{ needs.get_build.outputs.build_id }}
type: update
params:
channel: production
Hipcamp uses fingerprint to automatically check if changes are OTA-safe. If the fingerprint matches, it ships via OTA. If not, it waits for the next build. "This eliminates manual checks and potential human error," they reported. This pattern is now standard for teams shipping daily updates. citeweb_search:10#2
OTA Best Practices: Safe Deployments at Scale
Shipping OTA updates safely at scale requires more than the technical setup. These practices apply regardless of which OTA tool you use. citeweb_search:10#1
1. Never Deploy to 100% at Once
The single most important rule in OTA deployment: always start with a staged rollout. Push to a small percentage of your production user base first — 5% or 10% is a reasonable starting point. Monitor for installs, crashes, and error rates before expanding. Production environments surface issues that staging doesn't, and catching a problem at 5% is dramatically less costly than catching it at 100%. citeweb_search:10#1
2. Keep Staging and Production Channels Separate
Your staging channel should mirror production as closely as possible, but be accessible only to your internal team. Validate every update in staging before it touches a single production user. This isn't optional — it's the practice that separates teams who trust their OTA workflow from teams who treat every push as a gamble. citeweb_search:10#1
3. Have Your Rollback Plan Ready Before You Need It
A rollback reverts your production user base to the previous stable bundle. You should know exactly how to trigger one before you ever need it, and you should have tested the rollback process in staging. Teams that haven't pre-tested rollback tend to scramble when something goes wrong — which is the worst possible time to be figuring it out. citeweb_search:10#1
# Roll forward with a fix (often faster than rollback) eas update --channel production --message "Fix crash in checkout" # Or rollback to previous version eas update:rollback # Republish a known-good version eas update:republish --channel production --destination-channel production
4. Monitor Post-Deploy, Not Just Pre-Deploy
After pushing an update, watch your analytics dashboard. You want to see installs progressing steadily, error rates staying flat or improving, and version distribution shifting toward the new bundle. Any unexpected deviation from normal metrics is a signal to pause and investigate before expanding the rollout. citeweb_search:10#1
5. Document Your Process
Who has permission to push to production? What does a staged rollout look like step by step? What triggers a rollback? These should be written down and accessible to your team, not stored only in someone's head. citeweb_search:10#1
Security: Signing, HTTPS & SSL Pinning
OTA updates are powerful — but unmanaged, they introduce real security risks. Unauthorized bundles can compromise your app. Here's how production teams mitigate these risks. citeweb_search:10#5
1. Digitally Sign All Updates
Digital signatures ensure the authenticity and integrity of OTA-delivered code. Sign update bundles with a private key, while client applications validate the signature using the corresponding public key before applying any changes. This prevents the installation of tampered or spoofed updates. citeweb_search:10#5
2. Use HTTPS and TLS for All Communication
All communication between the client and server should occur over HTTPS with modern TLS protocols. This encrypts data in transit and mitigates man-in-the-middle attacks. Implementing SSL Pinning enhances security by allowing the app to trust only specific SSL certificates. citeweb_search:10#5
3. Secure Key Storage
Sensitive assets like private keys and credentials must be stored securely. On iOS, use the Keychain; on Android, use Keystore. These native storage solutions offer robust protection against unauthorized access. citeweb_search:10#5
4. Obfuscate Your JavaScript Code
If you're using the Hermes JavaScript engine, additional obfuscation might not be necessary — Hermes compiles JavaScript into bytecode by default, making it inherently more difficult to read and manipulate. citeweb_search:10#5
CI/CD Automation for OTA Updates
Manual OTA updates don't scale. The best teams automate their entire deployment pipeline — from code push to production rollout — with CI/CD integration.
GitHub Actions + EAS Updates Workflow
name: OTA Deploy to Production
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
- run: npm run lint
fingerprint-check:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: eas fingerprint:compare --build-id ${{ secrets.PROD_BUILD_ID }}
deploy-preview:
needs: fingerprint-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: eas update --channel preview --message "${{ github.event.head_commit.message }}"
deploy-production:
needs: deploy-preview
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: |
eas update --channel production \
--message "${{ github.event.head_commit.message }}" \
--rollout-percentage 10
🚀 Get Our OTA Deployment Playbook
Download our complete CI/CD templates for GitHub Actions, GitLab CI, and Bitrise — including fingerprint checks, staged rollouts, automatic rollback triggers, and Slack notifications. Used by 200+ React Native teams shipping daily updates.
Download Free PlaybookConclusion: The Future of Mobile Updates
The retirement of CodePush in 2025 was a wake-up call for the React Native ecosystem. OTA updates are not a luxury feature — they're a critical infrastructure component that demands a reliable, actively maintained platform.
In 2026, EAS Updates has emerged as the default choice for most teams. Its combination of Hermes bytecode diffing, fingerprint-based native change detection, phased rollouts, and Expo ecosystem integration makes it the most robust OTA solution available. For teams with existing CodePush integrations, Revopush offers the fastest migration path with SDK compatibility and managed infrastructure.
The principles of safe OTA deployment haven't changed: never ship to 100% at once, always have a rollback plan, monitor post-deploy metrics, and document your process. The tools have evolved, but the fundamentals remain the same.
The teams shipping most confidently in 2026 all follow similar patterns: they test on preview before production, use fingerprint to detect native changes, understand what can and can't be updated over-the-air, and use gradual rollouts with rollback capability. None of these require complex tooling — they're small adjustments that compound over time into fewer incidents, faster iteration cycles, and more confidence in your deployment pipeline.
Your Next Step: If you're still on CodePush or have no OTA solution, migrate to EAS Updates this week. The setup takes 1–2 days, and the first time you ship a critical fix in 2 minutes instead of 3 days, you'll wonder how you ever lived without it.