◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-05-24Advanced

Staged migration of a Rork-generated RN project to the New Architecture — notes from running six wallpaper apps in parallel

An implementation log for incrementally enabling Fabric and TurboModules on a Rork-generated React Native project, validated in parallel across six wallpaper apps. Covers flag design, compatibility triage, and KPI comparison based on actual production data.

Rork585React Native239New Architecture4FabricTurboModulesHermes9Staged Rollout3

✦ Premium Article

I'm Masaki Hirokawa, an independent app developer who has been shipping iOS and Android apps since 2014. The React Native projects that Rork generates are a wonderful starting point, but every time I take one toward production I run into the same question: when should I enable React Native's New Architecture — Fabric, TurboModules, and Bridgeless mode? In this note I'll walk through how I staged that migration across my own catalog of wallpaper apps. With more than 50 million cumulative downloads spread across six titles, I never had the courage to flip a single flag for all of them at once. What worked instead was breaking the risk into smaller pieces and lining everything up so I could compare numbers honestly.

Why I call this a "staged introduction" rather than a "migration"

React Native's New Architecture is the kind of change that feels like flipping a single switch — bridge gone, Fabric in, TurboModules everywhere. From the operator's side though, that one switch hides a lot of subtlety. My layered stack on top of Rork's scaffolding includes AdMob, Firebase, Skia, Reanimated, MMKV, and AppLovin MAX, replicated across six apps. I learned the hard way that turning newArchEnabled = true in a single push can silently break a non-Fabric native module during launch, and I sometimes didn't notice until TestFlight builds were already going out.

So in my own docs I now use the phrase "staged introduction" instead of "migration." I split it into four phases:

  1. Baseline measurement — keep Old Architecture and measure cold start, JS-thread load, and crash rate for two weeks.
  2. Flag plumbing — make newArchEnabled switchable per build via expo-build-properties.
  3. Canary rollout — pick the lowest-DAU app of the six and let it ride internal + TestFlight builds for a week.
  4. Horizontal expansion — promote apps one by one if KPIs are at least equivalent, roll back if anything regresses.

It sounds like a simple rule — "don't switch every production app at once" — but operationally that's the part that matters most. Rork's generated code is typically clean enough for the New Architecture; almost everything that breaks lives in the native dependencies I added on top later.

Step 1: How to gather baseline numbers

The baseline phase can stay on Old Architecture. Skipping this step is what leads to the vague "feels faster but I can't prove it" kind of decision later. I aim for at least 14 consecutive days of measurement.

I lock the measurement to these five signals:

  • Cold start: Firebase Performance Monitoring's _app_start at p50 and p95
  • JS-thread load: 30 samples of the primary navigation flow with the Hermes profiler
  • Native memory: same scenario three times under Xcode Instruments and Android Profiler
  • Crash rate: Crashlytics' Crash-free users for the trailing 14 days
  • ANR rate (Android): the 7-day median from Play Console's Android Vitals

I paste these five into a Notion table and append the same columns every two weeks afterward. Locking the format up front saves a surprising amount of time when comparing notes — nobody has to argue about what each number means.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A step-by-step setup for introducing the `newArchEnabled` flag into a freshly generated Rork project using expo-build-properties
✦A decision flow for wrapping non-Fabric legacy native modules through the Interop Layer while tracking remaining risk
✦A KPI comparison template covering cold-start, JS-thread load, and crash rate across six wallpaper apps over two-week cycles
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-10-13
Before You Ship: Go Looking for Your Own Keys Inside the Exported Expo Bundle
A key can be missing from your source and still be sitting inside the finished app. I ran expo export on Expo SDK 57, searched the bundle with grep and a short Node script, and recorded which secrets show up and which don't.
⬡ Dev Tools2026-09-04
EAS secret visibility does not keep a value out of your app — deciding prefix and visibility separately
The EXPO_PUBLIC_ prefix decides what ships inside your app; EAS visibility decides who can read it. Why stacking them blanks a value on OTA updates, and how to check your build.
⬡ Dev Tools2026-08-22
Every bulk replace exited zero. The damage was in the lines I did not delete
Run a bulk replace over generated code and the breakage lands on the neighbouring lines, not the matched ones. Here is what broke in a live project, and a dependency-free guard that checks the invariants a replace must preserve.