Home Services Work About Blog Contact Let's Talk
BlogReact Native
📱 React Native

React Native New Architecture in 2026: JSI, Fabric, TurboModules & Migration Guide

React Native's New Architecture has been in the works since 2018. It shipped as opt-in in 0.68, became stable in 0.73, and from 0.76 (released October 2024) it's the default for all new projects. By 2026, the pressure to migrate existing apps is real — major libraries have dropped support for the old bridge, and the performance improvements are significant enough that "we'll do it later" is a meaningful technical debt decision.

This post covers what actually changed at the architecture level, what the three major components (JSI, Fabric, TurboModules) do differently, and the step-by-step migration path for existing apps.

Old Architecture vs New Architecture: What Actually Changed

The old React Native architecture had a fundamental design problem: the JavaScript thread and the native thread could not communicate directly. All communication went through an asynchronous bridge — a serialised JSON message queue that was fast enough for most apps but broke down in performance-sensitive scenarios.

Old Architecture (Bridge)

  • JS ↔ Native via async JSON bridge
  • All native calls are batched and serialised
  • Shadow tree reconciliation on separate thread
  • NativeModules: lazy-ish, but not truly lazy
  • No synchronous JS ↔ Native calls possible
  • Layout calculated on JS thread, then sent over bridge

New Architecture (JSI)

  • JS ↔ Native via direct C++ JSI bindings
  • Synchronous calls available when needed
  • Fabric: concurrent rendering, priority scheduling
  • TurboModules: truly lazy-loaded native modules
  • Codegen: type-safe JS/Native interface at build time
  • Layout on Fabric's C++ shadow tree (faster)

JSI — JavaScript Interface

JSI (JavaScript Interface) is the foundation of the new architecture. It replaces the JSON bridge with a set of C++ host objects that the JavaScript runtime can interact with directly, synchronously, without serialisation overhead.

What this means practically:

  • Synchronous native calls: You can now call native code from JS and get a result back synchronously. Previously everything had to be async via callbacks/promises due to bridge serialisation.
  • Shared ownership: JS and native code can share C++ objects. A native value doesn't need to be serialised to JSON to be handed to JavaScript — the JS runtime gets a reference to the actual C++ object.
  • Any JS engine: JSI is engine-agnostic. React Native ships Hermes by default, but JSI enables third-party engines (V8, QuickJS) to plug in.

Performance impact: On apps with frequent small native calls (real-time animations, camera processing, Bluetooth device polling), the bridge serialisation overhead was a real bottleneck. JSI eliminates it. Scroll jank improvements of 40–60% are common on lists with complex native interactions.

Fabric — The New Renderer

Fabric is React Native's new rendering system. The old renderer calculated layout in JavaScript, sent the result over the bridge, and the native side applied it. Fabric moves layout calculation into C++ and integrates it with React's concurrent rendering model.

Key differences

  • C++ Shadow Tree: Layout is now computed in a C++ shadow tree (using Yoga layout engine compiled to C++) rather than in JavaScript. Faster and runs off the JS thread.
  • Concurrent rendering: Fabric supports React's startTransition, useDeferredValue, and priority scheduling. Low-priority updates don't block high-priority ones (e.g., user touch events aren't delayed by a heavy list render).
  • Synchronous rendering: Host components (native views) can be updated synchronously when needed, enabling things like scroll position synchronisation without jank.
  • View flattening: Fabric aggressively flattens unnecessary intermediate views, reducing the native view hierarchy depth and improving rendering throughput.

TurboModules — Lazy Native Modules

In the old architecture, all native modules were initialised on startup — even if the module was never used during that session. A large app with 40 native modules initialised all 40 at launch, regardless of user flow.

TurboModules are truly lazy. A native module is only initialised when first accessed from JavaScript. This directly reduces startup time proportional to the number of native modules your app has.

// Old NativeModule access (always loaded at startup)
import { NativeModules } from 'react-native';
const { MyModule } = NativeModules;

// TurboModule access (loaded only when first called)
import MyModule from './NativeMyModule'; // generated by Codegen
MyModule.doSomething(); // module initialised here, not at startup

Codegen

TurboModules require a typed interface defined using Codegen — a build-time tool that generates C++ bridge code from TypeScript or Flow type annotations. This enforces type safety between JS and native at the boundary and eliminates runtime type errors from bridge calls.

// NativeMyModule.ts — Codegen spec file
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  multiply(a: number, b: number): Promise<number>;
  getDeviceName(): string; // synchronous is now possible
}

export default TurboModuleRegistry.getEnforcing<Spec>('MyModule');

Migration Guide: Existing App to New Architecture

The migration is not a single toggle — it's a series of compatibility checks and updates. Here's the practical sequence:

1

Upgrade to React Native 0.75 or 0.76+

Run npx react-native upgrade or use the upgrade helper at react-native-community/upgrade-helper. Resolve all version conflicts before enabling new arch. Don't enable new arch and upgrade simultaneously.

2

Audit your third-party libraries

Run npx react-native-community-cli doctor and check each native module against the New Architecture Support table at react-native.dev. Look for the turboModuleEnabled or fabric flags in library changelogs. Libraries still using the bridge-only API will need alternatives or wrappers.

3

Enable New Architecture (opt-in test run)

On Android: set newArchEnabled=true in android/gradle.properties. On iOS: set RCT_NEW_ARCH_ENABLED=1 in Podfile. Build and run your full test suite — this surfaces incompatible native modules immediately.

4

Fix or replace incompatible libraries

Common replacements: react-native-camerareact-native-vision-camera (Fabric-native), react-native-maps v1.7+ (New Arch support added), older animation libraries → react-native-reanimated v3+ (Fabric-compatible). For in-house native modules, add Codegen specs.

5

Update custom native modules to TurboModules

Add a NativeXxx.ts Codegen spec file. Update the native (Java/Kotlin on Android, Objective-C/Swift on iOS) implementation to extend the generated TurboModule base class. Run pod install and the Android Gradle build to regenerate Codegen output.

6

Validate with Fabric-specific patterns

If you use UIManager.measureInWindow or similar layout APIs synchronously, verify they work under Fabric. Use useLayoutEffect instead of useEffect when you need synchronous layout reads after commit. Profile with the React Native DevTools flame graph for unexpected re-renders triggered by concurrent mode.

Common Migration Issues and Fixes

IssueCauseFix
Native module methods return undefined Module uses old bridge API, not TurboModule Add Codegen spec, update native implementation
App crashes on iOS after enabling new arch Incompatible Podfile or library not Fabric-ready Run pod install --clean-install, check library versions
Layout flicker on first render Component using useEffect for layout reads Switch to useLayoutEffect or onLayout callback
Animations janky after migration Animated API not fully Fabric-optimised in older RN versions Upgrade to react-native-reanimated v3+, use Worklets
Custom native view not rendering Native view component not using ViewProps from Codegen Create a Fabric NativeComponent spec with correct prop types
Metro bundler errors on Codegen types TypeScript strict mode incompatibility in spec files Use ?. optional chaining carefully; follow Codegen type constraints

Real Performance Gains to Expect

Based on community benchmarks and our own project migrations, New Architecture improvements vary by app type:

  • App startup time: 15–35% improvement on apps with many native modules (TurboModule lazy loading)
  • Scroll performance: 30–50% frame rate improvement on complex FlatList with custom native cells (Fabric view flattening + concurrent mode)
  • Animation jank: Near-zero dropped frames with Reanimated v3 Worklets on Fabric (runs on UI thread, bypasses JS)
  • Memory: 10–20% reduction from view flattening and eliminating bridge message queue overhead

Don't over-optimise upfront: The New Architecture doesn't automatically make slow code fast. Profile first — most performance issues in React Native come from unnecessary re-renders (fix with memo/useCallback), large list data without windowing (fix with FlashList), or synchronous JS work blocking the UI thread (fix with Worklets or moving to a worker).

React Native New Architecture vs Flutter in 2026

The New Architecture significantly narrows the performance gap between React Native and Flutter. Flutter's advantage has always been a fully native rendering engine (Impeller on iOS/Android) that bypasses the JS ↔ native bridge entirely. With Fabric + JSI, React Native now has a much leaner path to native rendering as well.

The remaining differentiators:

  • Flutter: Custom rendering engine (Impeller), pixel-perfect consistency across platforms, Dart language, better for complex animations and games
  • React Native: Uses actual native components (not custom-rendered), larger JS/React ecosystem, code sharing with React web, Expo ecosystem for rapid development

For enterprise internal tools and B2B apps, either works well in 2026. For consumer apps with complex UI or gaming adjacent experiences, Flutter still has the edge. For teams with strong JS/React expertise who need a web + mobile codebase, React Native with New Architecture is a solid, mature choice.

Summary

The React Native New Architecture is not just an incremental update — it's a fundamental redesign of how JS and native code communicate. The key takeaways:

  • JSI replaces the JSON bridge with direct C++ bindings. Synchronous native calls are now possible.
  • Fabric moves layout to C++ and enables concurrent rendering with React's priority scheduling.
  • TurboModules make native module loading truly lazy, cutting startup time on module-heavy apps.
  • Migration is a library audit + Codegen update, not a rewrite. Most apps take 1–3 weeks depending on native module count.
  • For new React Native projects in 2026: New Architecture is the default. There's no reason to use the bridge-based architecture for anything new.