Prefer reading? Everything in the video is covered below — plus extra code examples and diagrams.

If you've been building React Native apps for any length of time, you've felt it. The dreaded bridge jank. The mysterious async delays. The moment you realise that no matter how cleverly you optimise your JavaScript, there's a ceiling — and that ceiling was called the bridge.

Well, it's gone. As of React Native 0.83, the legacy architecture has been completely removed from the codebase. Not deprecated. Not disabled. Removed. And in its place is a completely reimagined runtime — faster, more capable, and finally ready to unlock everything that React 18 promised.

In this post, I'm going to break down every piece of the New Architecture, explain why the changes matter, and give you a practical migration path so you know exactly what to do next.

Why the Old Architecture Was Fundamentally Broken

To understand why the new architecture is such a big deal, you need to really understand what the old one was doing under the hood — and why it was always going to hit a wall.

React Native's original design was elegant in concept: run JavaScript on one thread, communicate with native code on another, and use a message-passing bridge to connect them. The problem wasn't the concept. The problem was the implementation.

Every single interaction between JavaScript and the native side required three things: serialize the data to JSON, send it asynchronously, and deserialize on the other end. And then the same process in reverse for the response. This wasn't just slow — it was architecturally limiting in ways that couldn't be fixed by throwing more hardware at the problem.

OLD ARCHITECTURE — EVERY NATIVE CALL JavaScript Thread serialize JSON Async Bridge ⚠ BOTTLENECK deserialize JSON Native Thread ~5ms overhead per native call 5 steps · Async only · JSON serialization on every crossing

The three fundamental problems that made the bridge a dead end:

  • Everything was async only. No synchronous access to native was possible under any circumstances. Even reading a simple value required a round-trip through the bridge.
  • JSON serialization on every crossing. Every piece of data had to be converted to a string, transmitted, and converted back — burning CPU and memory on every single native interaction.
  • React 18 was impossible. Concurrent rendering, Suspense, and Transitions require a multi-threaded renderer — something the old UIManager fundamentally couldn't support.

As of React Native 0.83 (2026), the legacy architecture has been completely removed. Setting newArchEnabled=false in your gradle.properties does nothing. If you haven't migrated, you need to start now.

The Four Pillars of the New Architecture

The New Architecture isn't one single change — it's a collection of four interlocking systems that together replace everything the bridge used to do. Think of them as four pillars holding up a new foundation.

THE FOUR PILLARS — NEW ARCHITECTURE JSI JavaScript Interface Direct C++ ↔ JS memory refs. No JSON. No async overhead. Fabric New Renderer C++ shadow tree replaces UIManager. Concurrent rendering enabled. Turbo Modules Lazy Native Modules Load only when needed. Massive startup improvement. Codegen Type Safety Layer Auto-generates native bindings from TypeScript. Build-time type safety.

These four don't work in isolation. JSI is the foundation that makes TurboModules and Fabric possible. Codegen provides the type-safe contract that TurboModules rely on. Pull any one of them out and the system doesn't work.

Deep Dive: JSI — The JavaScript Interface

JSI is the most fundamental change in the entire New Architecture, and it's worth spending real time understanding what it actually does.

In the old system, a native function call added around 5ms of overhead — not enormous on its own, but catastrophic when you're processing 60 frames per second or handling rapid user gestures.

With JSI, the JavaScript runtime holds direct C++ memory references to native objects. When JS calls a native function, it's calling a function pointer directly — no JSON, no queue, no async wait. The overhead drops from ~5ms to ~0.1ms. That's a 40x improvement.

OLD ARCHITECTURE JS Thread serialize JSON Serialize JSON ⚠ Bridge Queue ⚠ + 2 more steps back... vs NEW ARCHITECTURE (JSI) JS Thread direct ref · sync JSI C++ Layer direct call Native Layer 40× faster ~0.1ms vs ~5ms

A Real-World Example: VisionCamera

The best illustration of what JSI makes possible is VisionCamera 4.0. Processing a single 4K video frame produces around 30MB of raw pixel data. At 60 frames per second, you're moving roughly 1.8GB of data per second between JS and native. With the old bridge and JSON serialization, this was not just slow — it was impossible. With JSI, VisionCamera passes direct memory references to frame data without copying a single byte.

// This runs synchronously on every video frame via JSI
const frameProcessor = useFrameProcessor((frame) => {
  'worklet'
  // Direct memory access — no serialization, no bridge crossing
  const result = detectObjects(frame) // runs on native thread
  runOnJS(setDetections)(result)
}, [])

// OLD WAY: would have serialized 30MB to JSON per frame — impossible at 60fps
// NEW WAY: passes a memory reference — zero copy cost

Key insight: JSI doesn't mean everything becomes synchronous. Async is still the right choice for network calls, disk I/O, and anything that shouldn't block the JS thread. JSI just allows synchronous access when you need it — that optionality is what was missing before.

Deep Dive: Fabric — The New Renderer

While JSI handles how JavaScript communicates with native, Fabric handles how React Native renders your UI. The previous renderer, UIManager, maintained the shadow tree — the internal representation of your component layout — in JavaScript, which meant every layout calculation had to flow through the same async bottleneck. Fabric moves the shadow tree to C++, enabling it to be shared across multiple threads simultaneously.

FABRIC RENDERING PIPELINE React JSX (JavaScript) React Element Tree (JS) crosses to C++ via JSI ↓ C++ Shadow Tree (Fabric) Yoga Layout Engine Native Views — iOS & Android WHAT THIS ENABLES ✓ Concurrent rendering ✓ Automatic batching ✓ React 18 Suspense ✓ 60fps / 120fps UI

With Fabric, React Native can now interrupt and resume renders based on priority, batch multiple state updates automatically, use startTransition to mark non-urgent updates, and support Suspense for data fetching with native loading states.

import { startTransition, Suspense } from 'react'

// Mark a state update as non-urgent — Fabric can deprioritise it
const handleSearch = (text) => {
  startTransition(() => {
    setSearchResults(text) // won't block user input
  })
}

// Suspense for data — impossible with old UIManager
function ProfileScreen() {
  return (
    <Suspense fallback={<LoadingSkeleton />}>
      <UserProfile />
    </Suspense>
  )
}

Deep Dive: TurboModules & Codegen

TurboModules — The End of Eager Loading

In the old system, when your React Native app launched, it loaded every single native module you had registered — camera, Bluetooth, payments, push notifications — all of them, before your first screen rendered. For a typical production app with 20-30 native modules, this was a significant chunk of your cold start time, gone before you'd even rendered a single component.

TurboModules are lazy. They don't load until the first time your code actually calls them. If a user never opens your camera screen, the camera module never initialises.

// Define your module spec in TypeScript
import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'
import { TurboModuleRegistry } from 'react-native'

export interface Spec extends TurboModule {
  multiply(a: number, b: number): number
  getDeviceName(): string
}

// Codegen reads this spec and auto-generates native bindings
// The module ONLY loads when this line executes for the first time
export default TurboModuleRegistry.getEnforcing<Spec>('MyModule')

Codegen — Type Safety You Don't Have to Write

Codegen eliminates runtime type mismatches by generating native bindings directly from your TypeScript interfaces at compile time. If the types don't match, the build fails. Not the app — the build.

// android/app/build.gradle
react {
  jsRootDir = file("../src")
  libraryName = "MyAppModules"
  codegenJavaPackageName = "com.myapp.modules"
}
// Codegen auto-generates Java/Kotlin + ObjC/Swift bindings
// from your TypeScript specs at build time

The Performance Numbers

These numbers come from production migrations at Shopify and Meta — real apps, real users, real conditions.

PRODUCTION BENCHMARKS — SHOPIFY & META 43% Faster Cold Starts Time to interactive 39% Faster Rendering Frame render time 26% Less Memory App lifecycle avg 40× Native Call Speed JSI vs Bridge

The cold start improvement is largely from TurboModules — deferring 20-30 modules from startup to on-demand has a massive cumulative effect. The rendering improvement comes from Fabric's C++ shadow tree removing the async round-trip from layout calculations. The memory improvement comes from a combination of TurboModules and Hermes's improved garbage collection.

Your mileage will vary. Apps with fewer native modules will see smaller cold start gains. Apps with heavy list rendering and animations will see larger rendering improvements. Always benchmark your specific app before and after migration.

Migration Timeline — How We Got Here

MIGRATION TIMELINE RN 0.68 2022 First Opt-in Experimental flag. No library support. Most teams ignored it. RN 0.74 2024 Interop Layer Old libs work on New Arch via interop. Migration now feasible. RN 0.76 Late 2024 Default ON ★ New projects start on New Arch by default. Production-stable. RN 0.82 Early 2026 Bridge Disabled newArchEnabled=false stops working. Hard deadline hit. RN 0.83+ 2026 Legacy Gone Old arch code deleted from codebase. 📍 You Are Here The New Architecture is no longer optional — it IS React Native in 2026.

How to Migrate Your App (Step by Step)

Most migrations for apps without custom native modules take a few days to a week. Apps with significant custom native code can take two to eight weeks.

  1. Audit your dependencies first. Use npx expo-doctor for Expo projects, or check the React Native Directory for every library in your project. This tells you how hard your migration will be before you commit.
  2. Upgrade React Native. Target RN 0.76 or higher with Expo SDK 52 or higher. Use the RN Upgrade Helper — it shows you the exact diff of changes needed between versions.
  3. Enable the New Architecture. Add newArchEnabled=true to android/gradle.properties and RCT_NEW_ARCH_ENABLED=1 to your iOS Podfile. Then do a full clean build — not a cached one.
  4. Fix incompatible libraries. The Interop Layer handles many cases automatically. For libraries that still break, find a maintained fork, submit a PR, or find a replacement. Most popular libraries are already compatible.
  5. Test on real devices, especially Android. Low-end Android devices are where improvements are most dramatic — and where edge cases surface. Use React Native Inspector 2.0 to profile frame rates.
# android/gradle.properties
newArchEnabled=true
hermesEnabled=true
# ios/Podfile — add before your target block
ENV['RCT_NEW_ARCH_ENABLED'] = '1'

platform :ios, '13.4'
prepare_react_native_project!

target 'YourApp' do
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => true
  )
end

Library Ecosystem Status in 2026

As of May 2026, the library ecosystem is in very good shape — especially for the libraries most apps actually depend on.

  • React Navigation 7.2+ — Full support. Native Stack fully optimised for Fabric.
  • Reanimated 3.5.1+ — Full support. Worklets run via JSI — actually faster than before.
  • Gesture Handler 2.16+ — Full support.
  • Expo SDK 52+ — Full support. All Expo modules New Arch compatible.
  • VisionCamera 4.0+ — Full support. Built specifically around JSI frame processors.
  • MMKV 2.12+ — Full support. JSI-based from day one.
  • react-native-maps 1.14+ — Partial. Works via Interop Layer, full migration ongoing.
  • react-native-camera (legacy) — Unmaintained. Migrate to VisionCamera 4.0 instead.

83% of Expo SDK 54 projects built with EAS Build in January 2026 were already running on the New Architecture. If a library you depend on still doesn't support it, that's a signal about whether it's actively maintained.

What's Coming Next

React Native 0.84 — Hermes V1 Bytecode Caching

On subsequent app launches, Hermes reads pre-compiled bytecode instead of parsing and compiling your JavaScript bundle from scratch. Another cold start improvement on top of what TurboModules already delivered.

React Server Components in Expo Router

Certain components run on a server, stream their output to the mobile client, and the device never receives the JavaScript for those components at all. Smaller bundles, faster startup, server-side data access without building a separate API layer.

The React Compiler

Auto-memoizes your components and hooks at compile time. Large portions of your useMemo and useCallback calls become unnecessary — the compiler figures out what to memoize and does it for you.

Spatial Computing

visionOS and AR are being positioned as first-class React Native targets. Fabric's C++ rendering model is what makes supporting these platforms feasible without maintaining entirely separate codebases.

Your Action Checklist

If you've read this far, here's what to actually do today:

  1. Open package.json and check your current React Native version.
  2. If you're below 0.76, start planning your migration sprint.
  3. Run npx expo-doctor or check React Native Directory for every native library.
  4. Create a migration branch — don't do this on main.
  5. Measure your cold start time on a real device. You need a baseline.
  6. Enable newArchEnabled=true on Android and RCT_NEW_ARCH_ENABLED=1 on iOS.
  7. Fix any libraries that break. Most won't need it.
  8. Measure cold start again and compare the numbers.
  9. Ship it. The migration path is well-trodden at this point.

The New Architecture isn't a future upgrade — it's the present. Every week you stay on the old architecture is a week of performance you're leaving on the table. The migration path is clear, the ecosystem is ready, and the gains are real.