Skip to content
Malik Hamza Shabbir
Mobile Engineeringreact nativenew architectureapp rescuemobile

The Bridge Is Gone: Migrating a Legacy React Native App to 0.85 When New Architecture Is the Only Option

HSMalik Hamza ShabbirUpdated 9 min read

In short

As of React Native 0.85 (7 April 2026), the bridge is fully removed and the New Architecture is mandatory, with no newArchEnabled=false fallback. The framework bump is mechanical; the real work is your dependency graph. Audit every native module against the React Native Directory, replace abandoned libraries, and budget by dependency risk. See my app rescue service for fixed scoping.

The Bridge Is Gone: Migrating a Legacy React Native App to 0.85 When New Architecture Is the Only Option
On this page

As of React Native 0.85 (released 7 April 2026), the legacy bridge is fully removed. There is no newArchEnabled=false escape hatch anymore. If your app is stuck on a 0.7x release running the old Paper renderer, upgrading past 0.85 means committing to the New Architecture (Fabric + TurboModules + the JSI), and every native module you depend on has to support it or your app crashes on launch. In my app-rescue work, the migration is real but scopeable: the cost is almost never the React Native bump itself, it is the long tail of dependencies that were never rewritten for the new renderer.

Below is the audit, the libraries I see crash most often, and an honest read on effort and cost for rescuing a 0.7x Paper app.

What actually changed in React Native 0.85?

The short answer: the bridge is gone, so the New Architecture is no longer opt-in, it is the only architecture. Before this, even when New Arch was the default, you could set a flag and fall back to the old bridge-based Paper renderer to buy time. That flag no longer does anything in 0.85.

The bridge was the asynchronous, JSON-serialized message channel between JavaScript and native code. Everything went through it: every native module call, every UI update, every event. The New Architecture replaces it with three pieces:

  • JSI (JavaScript Interface), a C++ layer that lets JS hold direct references to native objects and call them synchronously, with no serialization.

  • TurboModules, native modules built on JSI that load lazily and expose a typed interface.

  • Fabric, the new rendering system that replaces Paper and renders the UI through C++ shadow nodes.


A library written for the old world registers itself as a bridge module and expects the bridge to be there at runtime. In 0.85 it is not. The app either fails to find the module, throws during native init, or renders a blank screen because a legacy native component has no Fabric equivalent. This is the core of why a forced migration is painful: the framework upgrade is mechanical, but the ecosystem around it is not uniformly ready.

Do I have to migrate, or can I stay on 0.7x?

You can stay on 0.7x, but only as a frozen, end-of-life decision, not a strategy. The moment you need a security patch, a new OS SDK, or a library version that dropped old RN support, you are forced forward.

This is the trap I see most. A 0.7x app keeps running for a while, then a real-world deadline lands on top of it. The two I am dealing with most right now:


When one of those forces an upgrade, you cannot stop at 0.78 anymore, because the path forward runs straight through 0.85 and the no-bridge cutover. So the honest framing for a 0.7x app is: you are not choosing whether to migrate, you are choosing when, and how much technical debt you carry into it.

How do I audit my dependencies before migrating?

Start with the React Native Directory and a hard list of every native dependency you ship. The directory tracks a New Architecture support flag per library, and that flag is the single best signal for whether a package will survive the cutover.

My process is the same every time. First, get the real dependency list, not what package.json claims is installed.

BASH
## List every package that ships native code
npx react-native config | grep -i "platforms"

## Or inspect what actually has native modules
ls node_modules/*/android/build.gradle 2>/dev/null
ls node_modules/*/*.podspec 2>/dev/null

Then run the upgrade tooling and the dependency check together:

BASH
## Align core deps and surface the diff for your version jump
npx @react-native-community/cli@latest doctor

## Check each native dep against the Directory's New Arch flag
npx react-native-community/directory check

For each native package, I record three things in a spreadsheet: does it support New Architecture, what is the minimum version that does, and is that version a major bump with its own breaking changes. That third column is where the hidden cost lives. Upgrading a library to its New Arch release often means jumping two majors and inheriting unrelated API changes.

A pure-JS library (no android/ or ios/ folder, no .podspec) is almost always fine. It never touched the bridge, so it does not care that the bridge is gone. Your risk is concentrated in the native modules.

Which libraries still crash on the New Architecture?

The reliable troublemakers are unmaintained native modules, anything doing custom native UI, and a few popular packages that needed a full rewrite to support Fabric. The pattern is consistent: the more a library reaches into native rendering or threading, the harder its migration was, and the more likely an old pinned version crashes.

Here is how I categorize what I find in an audit.








The animation layer deserves its own callout, because Reanimated's New Architecture story moved with it. If your app is on Reanimated 3, the upgrade also pulls in the worklets split, and that has its own migration steps that are easy to underestimate. I covered the specifics in migrating off Reanimated 3 without breaking your animations .

The genuinely expensive case is the abandoned native module. A package last published years ago, with an open issue thread full of "does this work with New Arch?" and no maintainer answer, is a dead end. You are not upgrading it, you are replacing it, and replacing a native module means re-testing every feature that touched it.

How do I actually do the migration without a big-bang rewrite?

Do it as a staged version climb, not a single jump from 0.7x to 0.85. Upgrade a few minor versions at a time, run the app, fix what breaks, commit, repeat. Big-bang jumps make it impossible to tell which version introduced which crash.

My typical sequence for a stuck 0.7x app:

  1. Freeze and branch. Pin every dependency, commit, and create a migration branch. You want a known-good baseline to diff against.

  2. Climb to the last pre-cutover minor first. Get to a recent 0.8x that still runs cleanly, fixing per-release breaking changes as you go. This isolates framework issues from architecture issues.

  3. Run the audit and pre-upgrade the safe natives. Bump every native dependency to its New Arch release while still on the old renderer where possible, so you are changing one variable at a time.

  4. Cross to 0.85. This is the no-bridge cutover. Now any remaining legacy module fails loudly.

  5. Triage crashes by category. Use the table above. Pure JS issues are config. Native crashes are either a missing upgrade or a library that must be replaced.


The single most useful diagnostic is the upgrade helper, which shows the exact file-level diff between your current version and the target:

BASH
## Generates the precise diff between two RN versions
## for every template file (gradle, podfile, MainApplication, etc.)
npx @react-native-community/cli upgrade

For the native side, a typical config change once you are on 0.85 looks like confirming New Arch is on and codegen runs:

PROPERTIES
## android/gradle.properties
## In 0.85 this is effectively the only mode; setting it false no longer
## restores the bridge. Keep it on and treat any "false" comments as dead.
newArchEnabled=true

RUBY
## ios/Podfile -- New Arch is wired through codegen automatically.
## A clean reinstall after the bump clears most stale native state:
## bundle exec pod deintegrate && bundle exec pod install

If your own app has custom native modules, those need to be rewritten as TurboModules with a spec file. That is real native work, not a config tweak, and it is one of the line items I scope separately.

What is the realistic effort and cost to rescue a 0.7x app?

Plan for weeks, not days, and budget by dependency risk rather than by React Native version number. A clean app with all-maintained, pure-JS-heavy dependencies can move in well under a week. An app with several abandoned native modules and custom native code is a multi-week project because you are doing replacement and re-testing, not just upgrading.

Here is the rough scoping I use, based on the audit output.






Dependency typeNew Arch statusWhat happens on 0.85 if not updatedTypical fix
Pure JS (lodash, date-fns, zustand)Always fineNothing, no native codeLeave as is
Maintained native modules on current majorsSupportedWorks after version bumpUpgrade to New Arch release
Navigation (react-native-screens)Supported on recent majorsCrash or blank screen on old pinsUpgrade screens + navigation together
Gesture and animation stacksSupported on recent majorsWorklet or gesture init failuresMove to current Reanimated + Gesture Handler
Maps, camera, video, WebViewSupported but version-sensitiveNative view not found, blank surfaceUpgrade, sometimes re-implement props
Abandoned native modulesNo support, no maintainerHard crash on launch or callReplace with a maintained alternative
App profileNative dep riskRealistic effortMain cost driver
Mostly JS, all deps maintainedLow2 to 5 daysVersion bumps and regression testing
Standard app (nav, maps, camera, animations)Medium1 to 2 weeksCoordinated major upgrades across the native stack
Heavy native, some abandoned modulesHigh3 to 6 weeksReplacing dead libraries, rewriting custom native modules
Custom native UI components on PaperHigh4 weeks and upRe-implementing components as Fabric components

The biggest budget mistake I see is scoping the React Native bump and forgetting the testing tail. After the cutover, every screen that touches a native module needs to be exercised on real devices, because a Fabric rendering difference or a TurboModule init failure does not always show up in the simulator. I treat device QA as its own line item, not a rounding error.

This is exactly the kind of work my app rescue and optimization service exists for: take a 0.7x app that can no longer ship, audit it against the Directory, give you a fixed scope by dependency risk, and bring it across the no-bridge line with a tested build at the end.

The honest takeaway

React Native 0.85 removing the bridge did not break your app, it removed the place you were hiding from a migration you already owed. The framework upgrade is mechanical. The work and the cost live entirely in your dependency graph: which native modules made the jump, which are abandoned, and how much of your own code reaches into native rendering.

Run the audit first. The Directory flag and your native dependency list will tell you within an hour whether this is a five-day job or a five-week one. If you want a second set of eyes on the audit or a fixed scope before you commit, my contact page is the place to start, and I am happy to look at the dependency list before you write a line of upgrade code.

FAQ

Can I still disable the New Architecture in React Native 0.85?

No, the legacy bridge was fully removed in 0.85 on 7 April 2026, so setting newArchEnabled to false no longer restores the old Paper renderer.

How do I know which of my dependencies will break on 0.85?

Check every native dependency against the React Native Directory's New Architecture flag and upgrade each one to its New Arch release before you cross the no-bridge cutover.

Do pure JavaScript libraries need to be updated for the New Architecture?

No, pure-JS libraries with no native android or ios code never used the bridge, so they keep working without changes on 0.85.

How long does it take to migrate a 0.7x app to 0.85?

A mostly-JS app can move in under a week, while an app with abandoned native modules or custom native UI can take three to six weeks because dead libraries must be replaced and re-tested.

What is the most expensive part of the migration?

Replacing abandoned native modules and re-testing every native-backed screen on real devices, not the React Native version bump itself, is where the real cost lives.

Working on something like this?

I build web apps, AI features, and mobile products for clients. If this article matches a problem you have, tell me about it.

Start a conversation
HS

Malik Hamza Shabbir · Full-Stack & AI Engineer

I build full-stack and AI products solo: a reputation SaaS in production, RAG pipelines, and React Native apps. I write from what I ship, not from documentation summaries.

Related articles