Introduction: Why the New Architecture Is Now Non-Negotiable
React Native's New Architecture — comprising Fabric, TurboModules, and the JavaScript Interface (JSI) — has graduated from experimental to the default in React Native 0.76+. The old architecture's asynchronous bridge created serialisation overhead, limited concurrent rendering, and prevented synchronous native calls. Fabric replaces this with direct C++ bindings that eliminate the bridge entirely, enabling synchronous native calls, concurrent rendering, and shared ownership of UI elements between JavaScript and native threads.
For teams still on the old architecture, the migration is no longer optional — new libraries and ecosystem tools increasingly require New Architecture support, and Meta has announced the legacy bridge will be deprecated. Apps that migrate typically see 30–50% reduction in interaction latency, smoother 120fps animations, and smaller bridge-related crash rates. This guide covers the complete migration path: architecture internals, pre-migration auditing, step-by-step conversion, native module migration, concurrent rendering adoption, performance benchmarking, and production rollout strategies.
Understanding the New Architecture: JSI, Fabric, and TurboModules
Three interconnected systems replace the old bridge:
- JavaScript Interface (JSI): A lightweight C++ API that lets JavaScript hold references to C++ host objects (and vice versa). Instead of serialising messages to JSON and sending them across the bridge asynchronously, JS code calls native methods directly and synchronously through JSI bindings. This eliminates serialisation overhead and enables data sharing without copying — critical for high-frequency operations like gesture handling and animations.
- Fabric Renderer: The new rendering system that replaces the old UIManager. Fabric creates a C++ shadow tree that's shared between JS and native threads, enabling concurrent rendering where UI updates can be prepared on background threads and committed atomically. Fabric supports synchronous layout measurement (no more layout thrashing from async measurement), multiple priority levels for rendering (urgent interactions vs background updates), and interruptible rendering where high-priority updates can preempt lower-priority work.
- TurboModules: The successor to Native Modules with three key improvements — lazy initialisation (modules load on first use instead of app startup), synchronous access via JSI (no bridge serialisation), and Codegen type safety where TypeScript/Flow specs generate native interfaces automatically, catching type mismatches at build time instead of runtime.
- Codegen: The type-safe bridge generator that reads TypeScript/Flow component and module specs and generates C++, Objective-C++, and Java/Kotlin interfaces. This ensures JavaScript types match native types exactly — no more runtime
NSDictionaryparsing orReadableMapcasting errors.
Step 1: Pre-Migration Audit and Dependency Assessment
Before writing any migration code, assess your project's readiness:
- React Native Version: Ensure you're on RN 0.72+ (minimum for New Architecture support). Ideally upgrade to 0.76+ where New Architecture is the default. Use the React Native Upgrade Helper to diff between versions and identify breaking changes in your specific version jump.
- Dependency Audit: Run
npx react-native-new-architecture-library-auditto scan all third-party dependencies for New Architecture compatibility. Categorise dependencies: ✅ fully compatible, ⚠️ has compatibility layer (interop mode), ❌ requires replacement. Check the React Native Directory for New Architecture badges on libraries. - Native Module Inventory: List all custom native modules and categorise by migration complexity — simple modules (data fetching, storage) convert easily; complex modules (camera, maps, video players) require careful Fabric component migration. Estimate LOE per module using the community migration guides.
- Interop Layer Strategy: React Native provides an interop layer that allows old-architecture native modules and components to work with the New Architecture without modification. Use this for third-party dependencies you can't control — but plan to migrate custom modules for full performance benefits.
- Testing Baseline: Before migrating, establish performance baselines — startup time (TTI), interaction latency (p50/p95), frame rates during complex animations, memory usage, and crash rates. These benchmarks let you objectively measure migration improvements.
Step 2: Enabling the New Architecture in Your Project
Enable the New Architecture incrementally with feature flags:
- Android Configuration: In
android/gradle.properties, setnewArchEnabled=true. This enables Fabric renderer and TurboModules across the Android build. For React Native 0.76+, this is the default — but verify yourbuild.gradleusesreact-native-gradle-pluginfor Codegen integration. Runcd android && ./gradlew cleanafter enabling. - iOS Configuration: In your Podfile, add
ENV['RCT_NEW_ARCH_ENABLED'] = '1'before theuse_react_native!call. Runcd ios && bundle exec pod installto regenerate Pods with Fabric and TurboModule support. Ensure Xcode build settings target C++17 or later for JSI compatibility. - Metro Configuration: Update
metro.config.jsto handle the New Architecture's Codegen output — ensurewatchFoldersincludes generated spec directories andresolver.sourceExtsincludes.cppand.hfor native interop files. - Hermes Engine: The New Architecture requires Hermes as the JavaScript engine (V8/JSC are no longer supported). Verify Hermes is enabled in both platforms — check
hermesEnabledinbuild.gradleand:hermes_enabled => truein Podfile. Hermes provides bytecode precompilation for faster startup and optimised garbage collection for lower memory usage. - Smoke Testing: After enabling, build and run the app — verify basic navigation, all screens render correctly, and no bridge-related crashes occur. The interop layer should handle most existing native modules automatically.
Step 3: Migrating Native Modules to TurboModules
Convert custom native modules for synchronous access and type safety:
- TypeScript Specs: Create spec files for each native module —
NativeMyModule.tsin your project's specs directory. Define the module interface usingTurboModuleRegistrySpec:export interface Spec extends TurboModule { multiply(a: number, b: number): number; getConstants(): { version: string }; }. Codegen reads these specs to generate native interfaces automatically. - Android (Kotlin): Replace
ReactContextBaseJavaModulewithNativeMyModuleSpec(generated by Codegen). Implement the spec interface directly — the compiler enforces that all methods match the TypeScript definition. Use@ReactModule(name = "MyModule")annotation and register in yourReactPackage. - iOS (Objective-C++): Replace
.mfiles with.mm(Objective-C++) to support C++ JSI bindings. Implement the generatedNativeMyModuleSpecJSIprotocol. UseRCT_EXPORT_MODULE()and implement synchronous methods that JSI can call without bridge serialisation. - Async to Sync Migration: TurboModules support both synchronous and asynchronous methods. Convert Promise-based methods that return simple values to synchronous calls for reduced latency —
getDeviceId(): stringinstead ofgetDeviceId(): Promise. Keep async for genuinely asynchronous operations (network, disk I/O). - Lazy Initialisation: TurboModules load on first access instead of app startup. Verify that modules with side effects (analytics, crash reporting) are accessed early enough — use
TurboModuleRegistry.get('MyModule')in your app's initialisation flow if needed.
Transform Your Publishing Workflow
Our experts can help you build scalable, API-driven publishing systems tailored to your business.
Step 4: Migrating Custom Native Components to Fabric
Convert custom native UI components to Fabric's shadow tree architecture:
- Component Specs: Create
MyComponentNativeComponent.tswithcodegenNativeComponent— define props using Codegen types:interface NativeProps extends ViewProps { color: string; size: Int32; onPress?: DirectEventHandler. Codegen generates platform-specific view managers and shadow nodes automatically.; } - Shadow Nodes (C++): Fabric uses C++ shadow nodes for layout calculation — replacing the old Java/ObjC layout measurement with Yoga C++ integration. For components with custom layout (e.g., custom text rendering), implement
measure()andlayout()in your shadow node subclass. Most components use the default Yoga-based layout. - Event Handling: Replace
RCTBubblingEventBlock/@ReactPropevents with Codegen-generated event emitters —DirectEventHandlerfor events that don't bubble,BubblingEventHandlerfor events that propagate up the component tree. Events are type-safe and validated at build time. - State Management: Fabric components can hold native state that's shared with JavaScript via
Statestructs. This enables patterns like synchronous scroll position reading without async bridge calls — critical for parallax effects, pull-to-refresh, and gesture-driven animations. - Backward Compatibility: Use the interop layer for components that are too complex to migrate immediately —
unstable_enableLogBoxandunstable_enableFabricRendererallow mixing Fabric and Paper components in the same app during migration. Plan for full Fabric conversion within 2–3 release cycles.
Step 5: Concurrent Rendering and Performance Optimisation
Leverage Fabric's concurrent rendering for fluid, responsive user interfaces:
- Concurrent Features: Fabric enables React 18's concurrent features —
useTransition()for non-urgent state updates (search filtering, list re-rendering),useDeferredValue()for derived computations that can lag behind primary state, andSuspensefor data loading boundaries. These prevent UI freezing during expensive re-renders. - Priority-Based Rendering: Fabric processes updates at different priorities — user interactions (taps, gestures) run at highest priority, interrupting lower-priority work like background data fetching. This ensures consistent 60/120fps even during complex state transitions. Use
startTransition(() => setFilter(value))to mark non-urgent updates. - Layout Animation: Fabric's
LayoutAnimationworks synchronously with the shadow tree — animate view additions, removals, and updates without JavaScript thread blocking. Combine withreact-native-reanimatedv3+ for worklet-based animations that run entirely on the UI thread. - Memory Optimisation: JSI's shared ownership model reduces memory copying between JS and native — large data structures (images, binary data) pass by reference instead of serialisation. Monitor memory with Xcode Instruments and Android Studio Profiler. Use
InteractionManager.runAfterInteractions()to defer heavy work until after animations complete. - Performance Benchmarking: Compare pre- and post-migration metrics — use
react-native-performancelibrary for TTI measurement,systrace(Android) and Instruments (iOS) for frame analysis. Target: TTI reduction >20%, p95 interaction latency <100ms, zero dropped frames during standard navigation.
Conclusion and MDS React Native Development Services
Migrating to React Native's New Architecture is a strategic investment in app performance, developer velocity, and ecosystem longevity. Key migration priorities:
- Architecture understanding — JSI for synchronous native access, Fabric for concurrent rendering, TurboModules for lazy-loaded type-safe native modules, Codegen for build-time type validation.
- Incremental migration — enable New Architecture with feature flags, use interop layer for third-party dependencies, migrate custom modules to TurboModules, convert native components to Fabric.
- Concurrent rendering — adopt useTransition, useDeferredValue, and Suspense for responsive UIs that never freeze during complex state transitions.
- Performance validation — benchmark TTI, interaction latency, and frame rates before and after migration to quantify improvements objectively.
MetaDesign Solutions provides expert React Native development and migration services — from New Architecture readiness auditing and TurboModule conversion through Fabric component migration, concurrent rendering optimisation, and production performance monitoring for organisations modernising their cross-platform mobile applications.




