React Native’s New Architecture, End to End - With Expo

If you’re starting a new React Native project in 2025 and don’t adopt the New Architecture, you’re signing yourself up for avoidable debt. With Fabric for rendering, TurboModules for native modules, and Bridgeless mode eliminating legacy overhead, you get a faster, more predictable platform that aligns with modern React (Concurrent features, Suspense) and JSI-first interop. Expo makes this shift dramatically easier—frankly, it’s the path of least resistance now.


Why switch (now)?


Do this: Expo-first migration plan

Enable the New Architecture (Expo)

{
  "expo": {
    "newArchEnabled": true
  }
}

Run a clean prebuild and build:

npx expo prebuild --clean && npx expo run:android
npx expo prebuild --clean && npx expo run:ios
# or with EAS
eas build -p android
eas build -p ios

For bare apps: toggle newArchEnabled=true in android/gradle.properties and enable it via Podfile.properties.json or Podfile on iOS.

What about Bridgeless? With RN 0.74+, New Arch implies Bridgeless by default. Expo SDK 53+ libraries support it; you’ll likely see “(NOBRIDGE)” logs in development—that’s expected.

Migrate UI libraries to Fabric-ready versions

Don’t drag old UI stacks into New Arch. Upgrade deliberately:

Pro tip: run npx expo-doctor@latest - Expo integrates React Native Directory data to flag incompatible deps right in your project. Bake this into CI.

Generate TurboModules from TS/Flow specs

This is the native module story in New Arch:

import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  ping(message: string): string;
}

export default TurboModuleRegistry.getEnforcing('NativeYourModule');

{
  "codegenConfig": {
    "name": "YourModuleSpec",
    "type": "modules",
    "jsSrcsDir": "specs",
    "android": {
      "javaPackageName": "com.yourapp.yourmodule"
    }
  }
}

Builds will run Codegen automatically (Gradle task on Android, CocoaPods script phase on iOS). Implement the generated interfaces on each platform, and you get type-safe, JSI-fast bindings.

Using Expo Modules? Great — Expo Modules are New-Arch ready by default and play nicely with TurboModules/Fabric. If you need custom native code, the Expo Modules API is the cleanest on-ramp.


Watch out (and how to handle it)

Upgrade discipline—versions matter.

The New Architecture is unforgiving about mismatched versions across RN, Reanimated, RNGH, and your list component. Pin versions explicitly in package.json, update lockfiles, and upgrade in small steps. Reanimated 4 only supports New Arch; FlashList v2 assumes New Arch; older RNGH versions may break.

Pin native deps that aren’t ready.

Some modules lag behind—especially those with heavy native code. Use Expo’s guidance for known problem libraries (e.g., react-native-maps caveats and alternatives). If a module isn’t ready, either pin a compatible version, swap to an Expo equivalent, or isolate it behind a feature flag until you can replace it.

CI build hygiene.

Adopt separate EAS build profiles for New Arch vs. legacy during migration (only temporarily). Run expo-doctor as a CI step. Fail the build if incompatible packages are detected so issues don’t creep into releases.

iOS/Android platform quirks.

Codegen is sensitive to Pod/Gradle state. When things act weird: clear derived data, pod deintegrate && pod install, ./gradlew clean, or expo prebuild --clean and rebuild. Keep your Podfile properties and Gradle flags in sync with the app config. (Expo’s guide shows the exact toggles for bare projects.)

Expect interop, but don’t rely on it forever.

Interop layers let many old-arch libs “sort of work,” but you’ll hit edges—especially for complex native views/gestures. Treat interop as a bridge to the bridge-less future, not a destination.


A pragmatic Expo rollout checklist

  1. Upgrade to latest Expo SDK (preferably 53+): It’s New Arch by default and has the fewest traps.
  2. Flip expo.newArchEnabled = true (if you’re on SDK 52), clean prebuild, and run a local build. Validate basic navigation, theming, network, and storage flows.
  3. Replace perf-critical UI pieces:
    • FlatList ➜ FlashList v2
    • Old gesture stacks ➜ current RNGH + Reanimated 4
    • Legacy modules ➜ Expo equivalents where possible.
  4. Add expo-doctor to CI and block incompatible deps.
  5. Harden TurboModules you own with TS specs + Codegen; remove any lingering bridge-only shims.
  6. Keep Bridgeless on: It’s the default with New Arch since 0.74; don’t fight it—fix the few APIs that still assumed the legacy bridge.

Opinionated take

In 2025, Expo + New Architecture is the standard. The ecosystem momentum (Reanimated 4, FlashList v2, Expo Modules, RN 0.74+ bridgeless by default) means you’ll spend less time wrestling with the runtime and more time shipping product. If you must support a legacy library that’s not ready, isolate it and keep the rest of your app modern. The payoff—cleaner boundaries, better concurrency, tighter perf on lists/gestures—shows up fast.

Ship the New Architecture. With Expo, it’s finally boring—in the best possible way.