The React Native upgrade timeline: what 6 versions behind actually means
One version behind costs roughly a week of focused engineering. Three versions behind costs three weeks if you're lucky. Six versions behind costs 4 to 12 weeks of elapsed work and is the threshold where in-house attempts most often stall.
The cost curve isn't linear. It's flat-then-jagged: each version step crosses a different set of breaking changes, build-tool jumps, and dependency cliffs.
The most predictive signal of how long your upgrade will take isn't the React Native version distance. It's the maintenance state of your dependency graph and the number of custom native modules.
"We're four versions behind on React Native." That sentence does almost nothing to predict how long the upgrade will take. Four versions could be a one-week project or a three-month one, depending on what else is in the codebase.
This post is the patterns we've seen across rescue engagements. The work is concentrated, the stall points are predictable, and the cost curve is jagged in places worth knowing about in advance.
The curve isn't linear
It's tempting to think "if one version takes a week, six should take six weeks." That's not the shape.
The first version step is mostly straightforward: the upgrade helper diff is small, dependencies usually slot in, the New Architecture flag stays put. Each additional version step adds work that scales worse than linearly because:
- The cumulative breaking-change list compounds
- You cross different build-tool requirement floors (Gradle versions, JDK versions, Xcode requirements)
- You cross into different default architectures (New Architecture flipped on at 0.76)
- Dependency peer ranges that worked for a small jump fail for a large one
- Patch-package patches that survived one version step often don't survive several
The result: the cost curve is flat for the first hop, jumps at certain version boundaries, then flattens again.
Cost by version distance
Rough engineering-week estimates from actual engagements. Variance is large; treat these as central tendencies, not promises.
| Versions behind | Typical engineering weeks | Notes |
|---|---|---|
| 1 (e.g. 0.75 → 0.76) | 0.5–2 | Single-version. Upgrade helper is well-behaved. |
| 2 (e.g. 0.74 → 0.76) | 1–3 | Often crosses the New Architecture default-on threshold. |
| 3 (e.g. 0.73 → 0.76) | 2–5 | Dependencies start needing genuine work. |
| 4 (e.g. 0.72 → 0.76) | 3–7 | Cumulative breaking changes start to compound. |
| 5 (e.g. 0.71 → 0.76) | 4–9 | Multiple library replacements likely. Build tool work required. |
| 6+ (e.g. 0.70 → 0.76) | 4–12 | The in-house stall zone. Productized engagement compresses time. |
| 10+ (e.g. 0.66 → 0.76) | 8–16 | Effectively a partial rewrite of dependencies. Plan accordingly. |
The "engineering weeks" is focused engineering — one or two engineers working on the upgrade as their primary task. In-house teams trying to do the upgrade in spare time alongside features typically multiply elapsed time by 2 to 4.
The real drivers of cost
Three things predict the timeline far better than version distance alone.
Dependency graph health
How many libraries in your package.json are still maintained? An app with 25 dependencies and 24 of them current upgrades fast. An app with 25 dependencies and 8 of them abandoned takes much longer — each abandoned library is a small replacement project.
Run npm outdated and check each library's release history to see which way you fall before you commit to an upgrade.
Custom native modules
Custom native modules written against the old NativeModule API usually keep working on the New Architecture through React Native's interop layers, which the React Native 0.82 release post says will stay for the foreseeable future. Test them there first. The work is in the modules that don't: ones that reach into bridge internals, do custom threading or event dispatch, or need synchronous calls. Migrating one of those to a TurboModule takes a few hours for a 50-line module and days to weeks for a 2,000-line one.
The team count matters too — most teams have 2–4 custom native modules they barely remember writing.
Patch-package depth
Patches are diffs against specific versions of files. The further you jump versions, the more patches stop applying. Each broken patch becomes a re-author, a delete, or a hunt for the upstream fix that may or may not exist.
An app with 3 patches is a quick triage. An app with 20 patches is a week of investigation work before the actual framework upgrade even starts.
Common stall points
Observed patterns where in-house upgrade attempts get stuck for weeks or months.
- The Reanimated upgrade. Reanimated 2 doesn't support the New Architecture, and no Reanimated 3 release supports React Native 0.82 or later, so an app crossing 0.82 lands on Reanimated 4 and its separate
react-native-workletspackage. The official guide says v2 API code works in 3.x without changes; the step to 4.x is where renamed and removed APIs, the New Architecture requirement, and native build changes show up. Teams that expected a version bump hit that mid-upgrade and pause. See the Reanimated migration guide. - One critical abandoned library. Often a payment SDK wrapper, an enterprise auth library, or a custom UI library. No drop-in replacement. Team spends weeks trying to upgrade, fork, or rewrite around it.
- A custom native module that breaks under interop. The team knew there was a custom native module. They didn't know what was in it. When it doesn't work through the interop layer, migrating it to a TurboModule means reverse-engineering the old code's intent.
- Gradle and JDK jumps. Older React Native templates used Gradle 6 or 7; the 0.76 template used Gradle 8.10.2 and the 0.87 template uses Gradle 9.4.1. The JDK moved from 11 to 17, which the React Native environment setup guide still recommends. Each jump can break Android builds in ways unrelated to your code.
- Xcode and CocoaPods drift. Each React Native version sets a minimum Xcode: 15.1 through 0.80, 16.1 for 0.81 to 0.86, and 26.0 for 0.87, per the React Native releases support policy. iOS pods need updates that cascade.
- Privacy manifest backfill. Since May 1, 2024, App Store Connect requires approved reasons for listed APIs your app uses, and privacy manifests and signatures for newly added SDKs on Apple's list of commonly used third-party SDKs (Apple). That applies whatever React Native version you're on, and old dependencies often predate it.
The half-life of an in-house upgrade attempt
An in-house React Native upgrade that doesn't ship within its initial estimate has a high abandonment rate. The shape we've seen:
- Initial estimate: "two sprints"
- Six weeks in: a critical library doesn't have a compatible version. Discussion pauses.
- Three months in: feature work has resumed. The upgrade branch is days behind
mainand stale. - Six months in: the upgrade branch is unmergeable. Quietly abandoned.
- Twelve months later: the upgrade is attempted again, from a starting point that's drifted further.
Anecdotally, roughly half of stalled in-house upgrades get abandoned and restarted later, rather than finished. The restart pays the cost of the first attempt plus the cost of additional drift.
Successful in-house upgrades have one thing in common: someone is given the upgrade as their only task for the duration. Upgrades attempted as a side-project alongside feature work stall at a rate so consistent it's essentially predictive.
Predicting your timeline
A rough formula based on the drivers above:
- Start with the version-distance baseline from the table above.
- Add 1 week per abandoned dependency that needs replacement.
- Add 1–4 weeks per custom native module that fails under the interop layer and needs TurboModule migration (depending on size).
- Add 1 week per 10 patch-package patches you're carrying.
- Multiply by 1 for focused engineering, 2 for split attention, 3+ for interleaved feature work.
A typical example: a team 5 versions behind, with 6 abandoned dependencies, 3 custom native modules (one large), and 12 patches, working with split attention.
- Baseline: 5 weeks
- Dependencies: +6 weeks
- Native modules: +1 + 1 + 4 = 6 weeks
- Patches: +1 week
- Subtotal: 18 weeks of focused work
- Split attention multiplier: ~36 weeks elapsed
That's 8–9 months for an upgrade the team probably estimated at "a few sprints." The math is uncomfortable but it's better to know it upfront.
One big upgrade vs many small ones
For teams already several versions behind, the choice is whether to step through versions one at a time or jump in one go.
Stepping (one version at a time):
- Each step is small enough to reason about
- Easier to debug — the breakage is bounded to one version's changes
- More total elapsed time — you're doing the install, build, test cycle N times
- Higher risk of stalling between steps as the team gets pulled to other work
Jumping (multi-version at once):
- Single concentrated effort, less calendar overhead
- Harder to debug — when something breaks, was it the 0.71 change or the 0.73 change?
- Lower total engineering time if it works smoothly
- Less risk of mid-upgrade interruption
For 1–3 versions behind, stepping is usually right. For 4+ versions, jumping is faster if you have the team focus to sustain it. For 6+ versions, productized engagements that own the work end-to-end are usually the cost-effective answer.
Want a scoped plan for your specific case?
Run the free scanner against your lockfile to see your React Native version and which installed package versions have published security advisories. For a timeline, book a call: we scope the upgrade against your actual codebase.
Frequently Asked Questions
How long does a React Native upgrade take?
For a single minor-version upgrade on a clean codebase, a few days. For a single minor with a moderate dependency graph, about a week. The non-linear part is when you're several minors behind — the work doesn't scale linearly with version distance, because each version step crosses into different breaking changes, build-tool requirements, and dependency boundaries. Six versions behind usually takes 4 to 12 weeks of focused work, not six times the one-version cost.
What makes a React Native upgrade take longer?
Three things, in roughly this order. First, abandoned dependencies that need replacement — every dead library is a small project. Second, custom native modules that don't work through the New Architecture's interop layer and have to migrate to TurboModules. Third, accumulated patch-package patches that no longer apply cleanly and have to be either reapplied, reauthored, or removed entirely. The framework itself is usually the smallest component of the total work.
Should I upgrade one version at a time?
For staying current, yes — single-minor upgrades are dramatically less risky than multi-minor jumps. For catching up when you're already 4+ versions behind, the choice is more nuanced. Stepping by single versions means doing the upgrade work multiple times, each time on a codebase still being changed by other developers. Jumping in one big upgrade is more disruptive but takes less calendar time. The right answer depends on your team's appetite for sustained focus vs incremental commits.
What are the common stall points in a React Native upgrade?
By far the most common is a dependency that doesn't have a version supporting the target React Native — either it's abandoned or the maintainer is behind. Other recurring stalls: native build failures from Gradle or Cocoapods version mismatches, Reanimated 2 to 3 migration, patches against React Native internals that no longer apply, custom native modules that need TurboModule rewrites, and privacy-manifest gaps on third-party SDKs.
Is it better to upgrade in-house or hire help?
In-house works well when you're one or two versions behind and have engineers who can carve out two weeks of focused time. It works poorly when you're four or more versions behind and the team is also expected to ship features — those upgrades tend to stall. A productized rescue service or experienced contractor compresses calendar time and de-risks the work, at the cost of the engagement fee. The break-even is roughly: if your in-house estimate is more than 6–8 weeks of elapsed time, outside help is usually cheaper end-to-end.
What does "half-life" mean in the context of a React Native upgrade?
Half-life is how long it takes for half of stalled in-house upgrades to actually ship vs get abandoned. Anecdotally, in-house React Native upgrades that don't ship within their initial estimate have a high abandonment rate — somewhere around 50% are quietly dropped within 6 months of the initial attempt, with the team going back to the old version. The work resumes a year later under more pressure, on a codebase that's drifted even further. Recognizing the half-life pattern is how you avoid being the team that learns it twice.