The Complete Guide to React Native OTA Updates
Everything you need to know about React Native OTA updates. From basics to advanced deployment strategies, this is the definitive guide for mobile developers.
Introduction
Over-the-Air (OTA) updates have fundamentally changed how React Native teams ship software. Instead of waiting days for App Store review every time you need to push a bug fix, you can deliver updates to your users in seconds.
This is the complete guide to React Native OTA updates. Whether you're a solo developer or part of a large engineering team, by the end of this guide you'll understand everything from the fundamentals to advanced deployment strategies.
What Are OTA Updates?
OTA (Over-the-Air) updates allow you to update your React Native app's JavaScript code and assets without going through the App Store or Google Play review process. When a user opens your app, the OTA SDK silently checks for updates, downloads any available patches, and applies them — all without requiring the user to visit the app store.
Why OTA Updates Matter
Traditional mobile app deployment:
1. Developer fixes bug
2. Submit to App Store / Google Play
3. Wait 1-7 days for review
4. Users must manually update
5. Weeks until majority adoption
Total time: 1-3 weeks
With OTA updates:
1. Developer fixes bug
2. Push OTA update via CLI
3. Update available in < 60 seconds
4. Users get update automatically on next launch
5. 90%+ adoption within 48 hours
Total time: Minutes
The Business Case
- Mean Time to Recovery (MTTR): Reduced from days to minutes
- User satisfaction: Critical bugs fixed before most users notice
- App store ratings: Fewer 1-star reviews from unfixed bugs
- Developer velocity: Ship multiple updates per day without friction
- Conversion rates: A/B test flows and optimize in real-time
How OTA Updates Work in React Native
React Native apps have a unique architecture that makes OTA updates possible:
The Two-Layer Architecture
┌─────────────────────────────────────┐
│ JavaScript Layer │
│ (React components, business logic, │
│ styles, navigation, assets) │
│ │
│ ✅ OTA Updatable │
├─────────────────────────────────────┤
│ Native Layer │
│ (Objective-C, Swift, Java, Kotlin, │
│ native modules, permissions) │
│ │
│ ❌ Requires App Store Submission │
└─────────────────────────────────────┘
The JavaScript layer runs inside an interpreter (Hermes or JavaScriptCore). Because it's interpreted code, you can replace the JavaScript bundle at any time without modifying the compiled native binary.
The Update Lifecycle
1. BUILD: Developer runs build → JavaScript bundle generated
2. UPLOAD: Bundle uploaded to OTA server
3. DIFF: Server computes differential patch
4. CHECK: App launches → SDK queries for updates
5. DOWNLOAD: SDK downloads patch in background
6. APPLY: On next restart, new bundle is loaded
7. VERIFY: SDK verifies bundle integrity
8. MONITOR: SDK monitors app health post-update
Architecture Overview
Client SDK
- Checking for available updates
- Downloading updates in the background
- Applying updates on app restart
- Verifying bundle integrity and signatures
- Monitoring health after updates
- Triggering automatic rollback if needed
Server
- Storing bundle versions and patches
- Computing differential patches
- Serving the right patch to each device
- Tracking rollout percentages
- Managing environments and channels
- Providing analytics and metrics
CDN
- Sub-100ms response times globally
- Automatic geographic routing
- Edge caching for popular updates
- High availability (99.99% uptime)
Architecture Overview:
Developer → CLI → SwiftPatch Server → CDN → Mobile App
↓
PostgreSQL
(metadata)
↓
S3/Object Storage
(bundle files)
Benefits of OTA Updates
1. Instant Bug Fixes
No more waiting for App Store review. Fix critical production bugs in minutes.
2. Faster Iteration
Ship multiple updates per day. Test ideas quickly and iterate based on real user feedback.
3. Higher Update Adoption
App store updates require manual user action. OTA updates are automatic — adoption rates are 90%+ within 48 hours compared to 30-50% for store updates.
4. A/B Testing
Test different UI variations, flows, or features with subsets of your users before rolling out to everyone.
5. Reduced Risk
Staged rollouts and automatic rollback mean you can deploy with confidence, knowing you have a safety net.
6. Lower Operational Costs
Fewer emergency app store submissions, faster incident resolution, and reduced support tickets.
Limitations: What You Can't Update
Understanding OTA limitations is crucial for planning your development workflow.
Cannot Update via OTA
- Native modules: Any Objective-C, Swift, Java, or Kotlin code
- Native dependencies: npm packages that include native code (e.g., react-native-camera with new native features)
- App permissions: Adding new permissions (camera, location, etc.)
- Build configuration: Changes to Info.plist, AndroidManifest.xml
- App metadata: App icon, launch screen, app name
- Native navigation: Changes to native navigation controllers
- OS-level features: Widgets, extensions, watch apps
How to Handle Native Changes
- Push the native changes through the App Store / Google Play
- Use OTA updates for any JavaScript changes that accompany the native update
- Target OTA updates to specific binary versions
# Target OTA updates to users on binary version 2.0 or higher
swiftpatch release --platform all --target-binary ">=2.0.0"
Getting Started with SwiftPatch
Prerequisites
- React Native 0.60 or higher
- Node.js 16 or higher
- npm or yarn
Step 1: Create a SwiftPatch Account
Visit swiftpatch.io and create a free account. The free tier includes 5,000 deploys per month.
Step 2: Install the CLI
npm install -g swiftpatch-cli
swiftpatch login
Step 3: Install the SDK
npm install swiftpatch
Step 4: Initialize SwiftPatch
// App.tsx
import { SwiftPatch } from 'swiftpatch';
SwiftPatch.init({
deploymentKey: 'YOUR_DEPLOYMENT_KEY',
autoRollback: true,
checkFrequency: 'ON_APP_RESUME',
});
export default function App() {
return (
// Your app components
);
}
Step 5: iOS Configuration
cd ios && pod install && cd ..
SwiftPatch automatically configures CocoaPods. No manual changes to AppDelegate needed.
Step 6: Android Configuration
SwiftPatch auto-links on React Native 0.60+. No manual configuration needed.
Step 7: Create Your App
swiftpatch app create --name "My App" --platform all
Step 8: Deploy Your First Update
# Make a code change, then:
swiftpatch release --platform all --description "My first OTA update!"
Step 9: Verify
Open your app, close it, and reopen it. The update will be applied on the second launch.
# Check deployment status
swiftpatch status
Configuration Options Explained
Update Strategy
SwiftPatch.init({
// IMMEDIATE: Download and apply right away (may restart app)
// ON_NEXT_RESTART: Download now, apply on next cold start
// ON_NEXT_RESUME: Download now, apply when app comes to foreground
updateStrategy: 'ON_NEXT_RESTART',
});
Check Frequency
SwiftPatch.init({
// ON_APP_START: Check once when app starts
// ON_APP_RESUME: Check when app comes to foreground
// MANUAL: Only check when you call SwiftPatch.checkForUpdate()
checkFrequency: 'ON_APP_RESUME',
});
Mandatory Updates
# Mark an update as mandatory (forces immediate install)
swiftpatch release --platform all --mandatory --description "Critical security fix"
SwiftPatch.init({
onUpdateAvailable: (update) => {
if (update.isMandatory) {
// Force update
SwiftPatch.applyUpdate();
}
},
});
Deployment Strategies
1. Immediate Deployment
Best for critical bug fixes:
swiftpatch release --platform all --rollout 100 --mandatory
2. Staged Rollout
Best for feature updates and non-critical changes:
swiftpatch release --platform all --rollout 1
# Monitor...
swiftpatch promote --rollout 10
# Monitor...
swiftpatch promote --rollout 50
# Monitor...
swiftpatch promote --rollout 100
3. Scheduled Deployment
Best for planned releases:
swiftpatch release --platform all --schedule "2026-02-15T10:00:00Z"
4. Environment-Based
Best for teams with QA processes:
swiftpatch release --environment staging
# QA testing...
swiftpatch promote --from staging --to production --rollout 1
Rollback Strategies
Automatic Rollback
SwiftPatch.init({
autoRollback: true,
healthCheckTimeout: 30000,
onRollback: (info) => {
console.log('Rolled back from', info.rolledBackVersion);
},
});
Manual Rollback
# Rollback to previous version
swiftpatch rollback
# Rollback to specific version
swiftpatch rollback --version 1.2.3
Preventive Rollback
If monitoring reveals issues before automatic detection:
# Halt rollout immediately
swiftpatch rollback --deployment dep_abc123
Security
Bundle Signing
# Generate keys
swiftpatch generate-keys --algorithm ed25519
# Sign releases
swiftpatch release --platform all --sign --private-key ./private.key
SwiftPatch.init({
publicKey: 'YOUR_PUBLIC_KEY',
requireSignature: true,
});
HTTPS Enforcement
All SwiftPatch communications use HTTPS by default. Certificate pinning is available for additional security.
Integrity Verification
Every bundle is verified against a SHA-256 hash before being applied. If the hash doesn't match, the update is rejected.
CI/CD Integration
GitHub Actions
name: Deploy OTA
on:
push:
branches: [main]
jobs:
deploy:
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 build
- run: npx swiftpatch release --platform all --rollout 1
env:
SWIFTPATCH_ACCESS_KEY: ${{ secrets.SWIFTPATCH_ACCESS_KEY }}
Other CI/CD Platforms
- CircleCI
- GitLab CI
- Bitbucket Pipelines
- Jenkins
- Azure DevOps
- AWS CodePipeline
Monitoring and Analytics
Dashboard Metrics
- Active deployments and their status
- Update adoption rates over time
- Rollback events and reasons
- Error rates per version
- Download success/failure rates
- Bundle sizes and patch sizes
CLI Monitoring
# View deployment status
swiftpatch status
# List recent deployments
swiftpatch deployments --limit 10
# View specific deployment details
swiftpatch deployment-info --id dep_abc123
Webhook Integration
# Set up webhooks for deployment events
swiftpatch webhooks add --url https://your-server.com/webhook --events deploy,rollback
Troubleshooting Common Issues
Update Not Being Applied
Symptoms: You deploy an update but users don't see changes.
- App hasn't been restarted after download
- Deployment key mismatch
- Binary version targeting excludes current users
- Rollout percentage hasn't reached the user
# Verify deployment status
swiftpatch status --verbose
Slow Update Downloads
Symptoms: Updates take too long to download.
- Verify differential patching is working (check patch size)
- Check CDN health status
- Ensure the user has reasonable network connectivity
Crash After Update
Symptoms: App crashes after applying an OTA update.
- Automatic rollback should handle this if enabled
- Check the SwiftPatch dashboard for error details
- Manually rollback if auto-rollback is disabled
swiftpatch rollback
Build Errors After SDK Installation
Symptoms: iOS or Android build fails after installing SwiftPatch.
Solutions:
# iOS: Clean and reinstall pods
cd ios && pod deintegrate && pod install && cd ..
# Android: Clean build
cd android && ./gradlew clean && cd ..
# Both: Clear Metro cache
npx react-native start --reset-cache
Advanced Topics
Custom Update Logic
For apps with specific update requirements:
SwiftPatch.init({
checkFrequency: 'MANUAL',
});
// Check for updates at a specific point in your app
async function checkUpdates() {
const update = await SwiftPatch.checkForUpdate();
if (update) {
if (update.isMandatory) {
await SwiftPatch.downloadAndApply();
} else {
// Download in background, apply on next restart
await SwiftPatch.downloadUpdate();
}
}
}
Background Updates
Download updates in the background while the user uses the app:
SwiftPatch.init({
updateStrategy: 'ON_NEXT_RESTART',
downloadInBackground: true,
onDownloadProgress: (progress) => {
// Optionally show progress to user
console.log(progress.percentage + '% downloaded');
},
});
Multi-App Management
If you manage multiple React Native apps:
# List all apps
swiftpatch apps list
# Deploy to specific app
swiftpatch release --app "my-app-ios" --platform ios
swiftpatch release --app "my-app-android" --platform android
Feature Flags with OTA
Combine OTA updates with feature flags for maximum flexibility:
// Feature flag configuration (OTA updatable)
const flags = {
newCheckoutFlow: false,
darkModeV2: true,
socialLoginEnabled: false,
};
// Toggle features via OTA update without code changes
export function isFeatureEnabled(flag: keyof typeof flags): boolean {
return flags[flag] ?? false;
}
FAQ
Q: Is OTA updating free?
A: SwiftPatch offers a free tier with 5,000 deploys per month. Paid plans start at $19/month for 25,000 deploys.
Q: Does OTA work with Expo?
A: Yes. SwiftPatch works with both bare React Native and Expo projects.
Q: How fast are updates delivered?
A: Updates are typically available within 60 seconds of deployment. Users receive them on their next app launch or resume.
Q: What happens if a user is offline?
A: The SDK will check for updates the next time the device has connectivity. No updates are lost.
Q: Can I target specific users or devices?
A: Yes. You can target by binary version, platform, and rollout percentage. Custom targeting (by user segment) is available on enterprise plans.
Q: How does OTA affect app size?
A: The SwiftPatch SDK adds approximately 200KB to your app binary. Patches are downloaded at runtime and replace the existing bundle.
Q: Is OTA compliant with App Store guidelines?
A: Yes. JavaScript OTA updates are explicitly allowed by both Apple (Section 3.3.2) and Google (Developer Program Policies).
Q: Can I use OTA with React Native New Architecture?
A: Yes. SwiftPatch fully supports React Native New Architecture (Fabric and TurboModules) as of version 2.0.
Conclusion
OTA updates are no longer optional for serious React Native teams. They're the difference between waiting days to fix a critical bug and fixing it in minutes. With SwiftPatch, you get the most advanced OTA platform available — differential patching, automatic rollback, staged rollouts, and enterprise security — all with a free tier to get started.
Your users deserve faster updates. Start shipping with confidence.
Ready to ship updates faster?
Get started with SwiftPatch for free. No credit card required.
Join WaitlistRelated Articles
Expo EAS Update Pricing: Cost, Bandwidth & What It Really Costs at Scale
Expo EAS Update feels cheap when you're starting out. Then your app grows. Here's how Expo actually bills for EAS Update, why costs grow faster than you expect, and what happens when you're shipping frequent releases to real users.
ComparisonExpo EAS Update Alternative — Best Expo Updates Replacement with Patch Updates
Expo EAS Update works well inside the Expo ecosystem. But as apps scale, teams need patch updates, rollback, internal testing, bare React Native support, and on-premise hosting. Here's how SwiftPatch compares.
GuidePatch Updates: The Modern CodePush Alternative
Microsoft CodePush is deprecated. Learn how to migrate to SwiftPatch, the modern OTA update platform for React Native with 98% smaller patches, automatic rollback, and enterprise security.