OTA Updates for React Native New Architecture
How to use OTA updates with React Native's New Architecture (Fabric renderer and TurboModules). Complete compatibility guide for modern React Native apps.
Introduction
React Native's New Architecture is the biggest change to the framework since its creation. With the Fabric renderer, TurboModules, and the JavaScript Interface (JSI), React Native apps are now faster, more responsive, and closer to native performance than ever before.
But this architectural shift has created a problem: most OTA update solutions don't work with the New Architecture. CodePush, the most popular OTA solution, has explicitly stated it does not support the New Architecture — and with its deprecation, it never will.
SwiftPatch fully supports React Native's New Architecture. This guide explains how the New Architecture works, why it creates OTA challenges, and how SwiftPatch solves them.
What Is the New Architecture?
React Native's New Architecture consists of three major components:
1. Fabric (New Renderer)
- Synchronous rendering: UI updates happen synchronously on the main thread when needed
- Concurrent rendering: Support for React 18 concurrent features (Suspense, transitions)
- Reduced bridge overhead: Direct C++ communication instead of async JSON bridge
- Better performance: Smoother animations and interactions
2. TurboModules (New Native Modules)
- Lazy loading: Modules are loaded only when first accessed
- Type-safe: CodeGen generates type-safe interfaces from TypeScript specs
- Direct JSI access: No serialization/deserialization overhead
- Faster startup: App starts faster because modules load on demand
3. JSI (JavaScript Interface)
- Direct communication: JavaScript can call C++ functions directly
- No bridge: Eliminates the async JSON bridge bottleneck
- Shared memory: JavaScript and native code can share memory
- Synchronous calls: Native calls can be synchronous when needed
Architecture Comparison
Old Architecture:
JS Thread ←→ [JSON Bridge (async)] ←→ Native Thread
↑ Bottleneck
New Architecture:
JS Thread ←→ [JSI (direct, sync)] ←→ Native Thread
↑ No bottleneck
The OTA Compatibility Challenge
The New Architecture creates specific challenges for OTA updates:
Challenge 1: CodeGen Dependencies
The New Architecture uses CodeGen to generate native code from TypeScript specifications. This means changes to TurboModule specs require regenerating native code — which can't be done via OTA.
// TurboModule spec (this generates native code)
export interface Spec extends TurboModule {
multiply(a: number, b: number): number;
// Adding a new method here requires native code regeneration
// This CANNOT be updated via OTA
}
Challenge 2: Fabric Component Specs
Similar to TurboModules, Fabric components have native specs that generate native view managers. Changes to these specs require a new binary.
Challenge 3: JSI Binding Changes
If you use custom JSI bindings (C++ functions exposed to JavaScript), changes to those bindings require recompilation — not OTA updatable.
Challenge 4: Bridge vs Bridgeless Mode
React Native 0.76+ introduced bridgeless mode, which removes the legacy bridge entirely. OTA solutions that relied on the bridge for bundle loading needed to be updated.
Why CodePush Doesn't Support New Architecture
CodePush's architecture was built around the legacy React Native bridge:
- Bundle loading: CodePush intercepted the bridge's bundle loading mechanism to swap in updated bundles. Bridgeless mode removes this mechanism.
- Module registration: CodePush registered as a native module through the old module system. TurboModules work differently.
- Maintenance: With App Center's deprecation, there's no team maintaining CodePush to add New Architecture support.
This is a fundamental limitation, not a simple bug fix. Supporting the New Architecture would require a complete rewrite of CodePush's native code — which Microsoft has no plans to do.
How SwiftPatch Handles New Architecture
SwiftPatch was designed with the New Architecture in mind from the start:
JSI-Based Bundle Loading
Instead of relying on the legacy bridge, SwiftPatch uses JSI for bundle loading:
SwiftPatch Bundle Loading (New Architecture):
1. App starts → SwiftPatch native module initializes via TurboModule
2. SwiftPatch checks for cached update
3. If update exists → loads updated bundle via JSI
4. If no update → loads default bundle
5. JavaScript executes with new or default bundle
TurboModule Registration
SwiftPatch registers as a TurboModule, compatible with both the old and new module systems:
// SwiftPatch TurboModule Spec (internal)
export interface Spec extends TurboModule {
initialize(config: Object): void;
checkForUpdate(): Promise<Object | null>;
downloadUpdate(): Promise<boolean>;
applyUpdate(): void;
getBundlePath(): string;
}
Fabric Compatibility
SwiftPatch doesn't render any UI components, so Fabric compatibility is inherent. The SDK operates entirely at the JavaScript engine level, below the renderer.
Bridgeless Mode Support
SwiftPatch fully supports bridgeless mode (React Native 0.76+):
Old Architecture: SwiftPatch → Bridge → Bundle Loader ✓
New Architecture: SwiftPatch → JSI → Bundle Loader ✓
Bridgeless Mode: SwiftPatch → JSI → Bundle Loader ✓ (No bridge needed)
JavaScript vs. Native Code in New Architecture
Understanding what's OTA updatable in the New Architecture:
OTA Updatable (JavaScript Layer)
Everything in your JavaScript/TypeScript code that doesn't change native specs:
// ✅ OTA Updatable: Component rendering logic
function ProductCard({ product }: Props) {
return (
<View style={styles.card}>
<Text style={styles.title}>{product.name}</Text>
<Text style={styles.price}>{formatPrice(product.price)}</Text>
</View>
);
}
// ✅ OTA Updatable: Business logic
function calculateDiscount(price: number, tier: string): number {
if (tier === 'premium') return price * 0.2;
if (tier === 'basic') return price * 0.1;
return 0;
}
// ✅ OTA Updatable: State management
const cartSlice = createSlice({
name: 'cart',
initialState: { items: [], total: 0 },
reducers: {
addItem: (state, action) => {
state.items.push(action.payload);
state.total += action.payload.price;
},
},
});
// ✅ OTA Updatable: API calls
async function fetchProducts(): Promise<Product[]> {
const response = await fetch('https://api.example.com/v2/products');
return response.json();
}
// ✅ OTA Updatable: Styles
const styles = StyleSheet.create({
card: { padding: 16, borderRadius: 12, backgroundColor: '#fff' },
title: { fontSize: 18, fontWeight: 'bold' },
price: { fontSize: 16, color: '#059669' },
});
NOT OTA Updatable (Native Layer)
Changes to native specs, native code, or platform configuration:
// ❌ NOT OTA Updatable: Adding new TurboModule methods
// (requires CodeGen to regenerate native code)
export interface Spec extends TurboModule {
existingMethod(): void;
newMethod(): void; // Adding this requires new binary
}
// ❌ NOT OTA Updatable: New Fabric component props
// (requires CodeGen to regenerate native code)
export interface NativeProps extends ViewProps {
existingProp: string;
newProp: number; // Adding this requires new binary
}
The Gray Area: Using Existing Native Methods Differently
This is OTA updatable because you're only changing the JavaScript call pattern, not the native interface:
// ✅ OTA Updatable: Different usage of existing native methods
// The TurboModule spec hasn't changed, only how JS calls it
// Before
useEffect(() => {
NativeAnalytics.track('screen_view', { screen: 'home' });
}, []);
// After (changed what we track - JS only change)
useEffect(() => {
NativeAnalytics.track('screen_view', {
screen: 'home',
timestamp: Date.now(),
session_id: getSessionId(),
});
}, []);
Setup Guide for New Architecture Projects
Step 1: Ensure New Architecture Is Enabled
# iOS: Check Podfile
# newArchEnabled should be true
cat ios/Podfile | grep newArchEnabled
# Android: Check gradle.properties
cat android/gradle.properties | grep newArchEnabled
Step 2: Install SwiftPatch
npm install swiftpatch
Step 3: iOS Setup
cd ios && pod install && cd ..
SwiftPatch's podspec includes New Architecture support automatically. The TurboModule spec is pre-configured.
Step 4: Android Setup
SwiftPatch auto-links on React Native 0.60+. For New Architecture, the TurboModule is registered automatically.
Step 5: Initialize
// Same initialization as always
import { SwiftPatch } from 'swiftpatch';
SwiftPatch.init({
deploymentKey: 'YOUR_DEPLOYMENT_KEY',
autoRollback: true,
checkFrequency: 'ON_APP_RESUME',
});
No additional configuration needed for New Architecture. SwiftPatch automatically detects whether your app uses the old or new architecture and configures itself accordingly.
Step 6: Verify
npx react-native run-ios --configuration Release
Check logs for:
[SwiftPatch] Architecture: New (Fabric + TurboModules)
[SwiftPatch] Bridgeless: true
[SwiftPatch] Initialized successfully
Bridgeless Mode Support
React Native 0.76 introduced bridgeless mode as the default. SwiftPatch has full bridgeless support:
Bridge Mode Detection:
App Start → SwiftPatch checks environment
→ Bridge present? → Use bridge-based loading
→ Bridgeless? → Use JSI-based loading (default for 0.76+)
No Configuration Changes Needed
// Same code for bridge and bridgeless
SwiftPatch.init({
deploymentKey: 'YOUR_KEY',
autoRollback: true,
});
// SwiftPatch handles the difference automatically
React Native 0.76+ Compatibility
SwiftPatch is tested against every React Native release. Current compatibility:
| React Native Version | Architecture | SwiftPatch Support |
|---|---|---|
| 0.60 - 0.67 | Old Architecture | Full Support |
| 0.68 - 0.71 | Old + New (opt-in) | Full Support |
| 0.72 - 0.75 | Old + New (opt-in) | Full Support |
| 0.76+ | New Architecture (default) | Full Support |
What Changed in 0.76+
- New Architecture is now the default
- Bridgeless mode is enabled by default
- React 18 features (concurrent rendering) are fully available
- InteropLayer provides backward compatibility for old modules
SwiftPatch works with all of these changes out of the box.
Testing OTA Updates with New Architecture
Testing Checklist
New Architecture OTA Testing:
[ ] Deploy update that changes only JS logic
[ ] Verify update downloads and applies correctly
[ ] Test with Fabric components (rendering works post-update)
[ ] Test with TurboModules (native calls work post-update)
[ ] Test automatic rollback triggers correctly
[ ] Test on bridgeless mode
[ ] Test on devices with old architecture (backward compat)
[ ] Verify bundle integrity check passes
[ ] Test on React Native 0.76+
[ ] Test with concurrent features (Suspense, useTransition)
Debugging Tips
// Enable verbose logging for debugging
SwiftPatch.init({
deploymentKey: 'YOUR_KEY',
logLevel: 'verbose', // 'verbose' | 'info' | 'warn' | 'error'
});
Verbose logs will show:
[SwiftPatch] Architecture detected: New Architecture (Fabric + TurboModules)
[SwiftPatch] Bridge mode: Bridgeless
[SwiftPatch] Bundle loading mechanism: JSI
[SwiftPatch] Checking for updates...
[SwiftPatch] Update available: v2.3.1 (patch size: 187KB)
[SwiftPatch] Downloading patch...
[SwiftPatch] Download complete. Verifying integrity...
[SwiftPatch] Bundle hash verified ✓
[SwiftPatch] Bundle signature verified ✓
[SwiftPatch] Update staged for next restart.
FAQ
Q: Does SwiftPatch work with React Native 0.76's default New Architecture?
A: Yes. SwiftPatch has supported the New Architecture since our 2.0 release. No additional configuration is needed.
Q: Can I update Fabric components via OTA?
A: Yes, as long as you're not changing the native component spec. Changes to the JavaScript rendering logic, props handling, and styles are fully OTA updatable.
Q: Can I update TurboModule JavaScript code via OTA?
A: Yes, as long as you're not changing the TurboModule spec (the interface definition that CodeGen uses). Changes to how you call existing TurboModule methods are OTA updatable.
Q: What about the InteropLayer for old modules?
A: SwiftPatch works with modules using the InteropLayer (old-style modules running in New Architecture). Updates to JavaScript code calling these modules are OTA updatable.
Q: Does bridgeless mode affect OTA updates?
A: No. SwiftPatch uses JSI-based bundle loading that works in both bridge and bridgeless modes. The switch is transparent.
Q: I'm migrating to New Architecture. Do I need to change my SwiftPatch setup?
A: No. SwiftPatch automatically detects the architecture and configures itself. Your existing setup will continue to work after migrating to the New Architecture.
Q: Can I use OTA updates during the migration to New Architecture?
A: Yes. During migration, you may have some components on the old architecture and some on new. SwiftPatch handles both simultaneously.
Q: Does SwiftPatch support React 18 concurrent features?
A: Yes. Concurrent rendering (Suspense, useTransition, useDeferredValue) is fully compatible with SwiftPatch OTA updates.
Q: What about Hermes bytecode compatibility?
A: SwiftPatch generates differential patches at the Hermes bytecode level when Hermes is enabled, ensuring optimal patch sizes for compiled bundles.
Q: Can I use custom JSI bindings with SwiftPatch?
A: Yes. Custom JSI bindings are native code and won't be affected by OTA updates. Your JavaScript code that calls those bindings is OTA updatable.
Conclusion
React Native's New Architecture is the future of the framework, and your OTA solution needs to keep up. CodePush can't. Expo Updates requires Expo.
SwiftPatch supports the New Architecture natively — Fabric, TurboModules, JSI, bridgeless mode, and React Native 0.76+ — with zero additional configuration.
The same simple setup, the same powerful features, the same peace of mind. Whether you're on the old architecture or the new one, SwiftPatch just works.
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.