React Native New Architecture Migration: The Checklist I Wish I Had in 2026

I've migrated two production React Native apps to the New Architecture (Fabric + TurboModules + Codegen) in the last few months. The official upgrade guide is fine for fresh apps, but for anything older.

React Native New Architecture Migration 2026

I've migrated two production React Native apps to the New Architecture (Fabric + TurboModules + Codegen) in the last few months. The official upgrade guide is fine for fresh apps, but for anything that has been around since the 0.6x days, it skips most of the steps that actually consume time.

This is the condensed checklist I now follow on every migration. The full version with library compatibility tables and Android-specific gradle traps lives on the canonical link at the bottom.

1. Audit before you flip the flag

Before touching newArchEnabled, run an inventory. The two things that will break you are custom native modules and third-party libraries that haven't shipped Fabric support.

# find every native module reference
grep -r "RCT_EXPORT_MODULE\|@ReactModule" ios/ android/ node_modules/ --include="*.m" --include="*.mm" --include="*.java" --include="*.kt" | wc -l

If the number is north of 20, plan to use interop mode (more on that below) rather than a big-bang switch.

2. Update codegen specs first, flip flags second

The single biggest mistake I see is enabling newArchEnabled=true before the TypeScript specs exist. Codegen will generate empty bindings and your modules will silently no-op.

For each custom module, write the spec first:

// specs/NativeAudioEngine.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  start(sampleRate: number): Promise<boolean>;
  stop(): void;
  readonly getConstants: () => { maxChannels: number };
}

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

Then run codegen and inspect the generated headers in ios/build/generated/ios/ before you change a single native file.

3. Use interop mode

The interop layer is the most underrated feature of the New Architecture. It lets old bridge modules and TurboModules coexist in the same app. Without it, you'd need every third-party lib to ship Fabric support on the same day.

Enable in Podfile:

use_react_native!(
  :path => config[:reactNativePath],
  :new_arch_enabled => true,
  :fabric_enabled => true,
  :bridgeless_enabled => false  # keep this false during migration
)

Bridgeless mode is the real endgame, but flipping it on day one is how migrations die.

4. Clear every cache, every time

This one cost me three hours of confusion. Codegen output is aggressively cached and stale output will give you compilation errors that point at the wrong file.

# the only cache reset that actually works
watchman watch-del-all
rm -rf node_modules ios/Pods ios/build android/app/build android/build android/.gradle
rm -rf ~/Library/Developer/Xcode/DerivedData/*
rm -rf $TMPDIR/metro-* $TMPDIR/react-*
yarn install && cd ios && pod install && cd ..

5. Verify Fabric is actually on

Add a sanity check at app boot. If you don't, you can ship a build that silently falls back to Paper and not notice for a week.

if (__DEV__) {
  const isFabric = (global as any).nativeFabricUIManager != null;
  console.log('[arch] Fabric:', isFabric);
  console.log('[arch] TurboModules:', (global as any).__turboModuleProxy != null);
}

If either logs false, your migration didn't take effect even if the build succeeded.

6. Watch for the library traps

These are the libraries that gave me the most trouble. Versions below the listed minimum will silently disable Fabric on at least one platform:

  • react-native-screens — needs 3.32+
  • react-native-reanimated — needs 3.15+, worklet cleanup semantics changed
  • react-native-gesture-handler — needs 2.18+
  • react-native-svg — needs 15.2+
  • react-native-mmkv — Fabric-ready since 2.12

7. Animations need a re-test pass

Reanimated 3 on Fabric handles worklets slightly differently inside useEffect cleanups. On iOS specifically, synchronous shared-value reads during unmount can crash. Wrap them:

useEffect(() => {
  return () => {
    runOnUI(() => {
      'worklet';
      sharedValue.value = 0;
    })();
  };
}, []);

Wrapping up

Migration is genuinely worth it — startup time on my larger app dropped from 1.8s to 1.1s on a mid-range Android device, and memory at idle dropped roughly 18%. But the cost-of-entry is dominated by the gotchas above, not the conceptual model of Fabric itself.

Full benchmark numbers, the complete library compatibility table for 2026, and the Android gradle configuration that actually works are on the original post: https://reactnativerelay.com/article/react-native-new-architecture-migration-checklist-2026

Article changelog (1)
  • — Expanded with TL;DR, table of contents, or additional sections
Jake Morrison
About the Author Jake Morrison

React Native lead engineer who's shipped six apps and learned six different lessons. Bullish on the New Architecture.