Should you rewrite in Flutter or upgrade React Native?
The Flutter vs React Native framework debate is decided enough that nobody needs another comparison post. The harder question — "is upgrading worth it vs rewriting in Flutter?" — barely has good content.
For almost every production app, upgrading is faster, cheaper, and less risky. Rewrites take 6–18 months. Upgrades take 4–12 weeks. The rewrite reintroduces every edge case the original app already solved.
Full disclosure: we run a productized React Native upgrade service. We've also walked away from prospects whose situation genuinely called for a rewrite. The three cases are below.
An engineer on your team has been quietly evaluating Flutter. The React Native version is years behind. The dependency graph is a mess. The last upgrade attempt stalled.
The question gets reframed: "Should we just rewrite in Flutter?"
It's a reasonable question. It's also rarely the right answer. This is the math.
The honest default: upgrade
Your existing React Native app contains years of accumulated decisions. Every weird if-statement is a bug that was reported by a customer and fixed by someone who's no longer on the team. Every retry policy was tuned through a production incident. Every analytics event was added because someone needed the data.
None of that survives a rewrite. The new Flutter app starts from "what does the spec say it should do?" — which is a long way from "what does the deployed app actually do for half a million users?"
Rewrites get marketed as "do it right this time." They're usually "do it again from scratch" — and the first version was already mostly right.
Timeline comparison
| Path | Typical timeline | What's actually happening |
|---|---|---|
| Productized React Native upgrade (3+ versions behind) | 2–6 weeks | One team, fixed scope, all attention on the upgrade |
| In-house React Native upgrade (3+ versions behind) | 2–6 months | Same work, interleaved with feature development, often stalled mid-flight |
| Flutter rewrite of small app (under 30 screens) | 3–6 months | New stack, parity work, edge cases re-discovered |
| Flutter rewrite of medium app (30–100 screens) | 6–12 months | Parallel maintenance of original app plus the rewrite |
| Flutter rewrite of large app (100+ screens, native integrations) | 12–24 months | Multi-team effort, edge-case backlog never fully closes |
The ranges aren't conservative. They're observed.
The hidden costs of rewriting
The estimate your team writes down isn't the cost. The cost is everything you stop doing or have to redo.
Lost edge-case coverage
Your app handles a thousand tiny situations that aren't in the spec. The Android user with locale set to Arabic on a 2018 phone. The iOS user who denied notification permissions and then enabled them. The subscription user whose card declined three times last month.
Every one of those was a bug, a fix, a regression test, or a workaround. The rewrite starts without any of them. You'll rediscover them in production over the next six months.
Parallel development
The old app doesn't get to stop shipping during the rewrite. Customers want features. Bugs need fixing. Whatever your team builds on the old codebase has to be rebuilt on the new one before the cutover.
Some teams freeze feature work on the old app. Then competitive pressure resumes feature work three months in. Then both codebases drift, and the cutover gets pushed.
Team retraining
Your engineers know React, JavaScript, and your app. Flutter is Dart, a different framework model, a different state management ecosystem, a different testing story, a different native integration model.
Senior engineers absorb this fast. The lost productivity during the absorption period is real, just hidden in the timeline.
Hiring and retention risk
Engineers on long rewrites get demoralized. They joined to ship product, not to rebuild the product they already shipped. Attrition during a 12-month rewrite is real — and an engineer leaving mid-rewrite is much more disruptive than an engineer leaving on a stable codebase.
The hiring market for Dart/Flutter is smaller than for React/React Native. Replacing the engineer who leaves is harder, not easier.
Store transition risk
If you're replacing the existing app rather than shipping a new one, the cutover is real. Different binary, possibly different bundle ID, different app size, different reviews, different analytics baseline.
Push notifications, deep links, payment receipts, account linking, install attribution — every integration with an external system needs validation through the cutover.
The hidden costs of upgrading
Honesty cuts both ways. Upgrading isn't free either.
- Dependency hell. The further behind you are, the more libraries you have to upgrade in lockstep. Some are abandoned. Some have breaking changes. Some require native module work.
- Native module rebuilds. Custom native modules written against the old bridge need migration to TurboModules for the New Architecture.
- Pod and Gradle work. Cocoapods, Gradle, JDK versions, Xcode versions, Android SDK levels — the platform tooling has all moved. The upgrade pulls those forward too.
- Test debt comes due. If the app has thin test coverage, the upgrade exposes how much regression risk was being absorbed by manual QA.
A planned upgrade by experienced engineers absorbs these. An upgrade attempted in spare time alongside feature work usually stalls on them.
When a rewrite actually makes sense
Three cases where Flutter is the right call.
The app is genuinely small
Under 30 screens. Single-platform native integration. Simple data model. No deep dependency on React Native specific libraries (no Reanimated complexity, no custom native modules, no heavy use of platform APIs).
For an app like this, a rewrite might genuinely be 3 months instead of 9. At that scale the rewrite is competitive with a deep upgrade.
The product has shifted toward Flutter's strengths
Heavy custom UI. Game-like visuals. Complex animation pipelines. A design language that doesn't map cleanly to native controls.
Flutter's rendering model — drawing everything itself rather than wrapping native widgets — is genuinely better for some product directions. If yours is one of them, the framework switch is the work, not the side effect.
Non-technical strategic reasons
The company has standardized on Dart. Backend services are written in it. The team has invested in Flutter for other apps. The hiring market in your region favors Flutter. The CTO has a strong preference and you don't get to overrule it.
These are real reasons. Don't dress them up as engineering arguments. "We're moving to Flutter for strategic reasons" is honest. "Flutter performs better on synthetic benchmarks" is fig leaf.
What's not on the list: "We're behind on React Native upgrades and don't want to deal with it." That's the path-of-least-resistance fantasy. The path of least resistance is to stop being behind, not to swap frameworks.
The teams that rewrote and were glad they did, almost all had at least two of the three cases above. The teams that rewrote and regretted it, almost all had one — usually "we're tired of React Native" — and were 9 months into a 18-month rewrite when they realized they'd be re-fixing the same edge cases in a new language.
How to decide
Run the math, not the vibes.
- Estimate the upgrade. Get a fixed-price quote, or run an internal estimate. Honest number, including dependency work and native module migration.
- Estimate the rewrite. Multiply the team's first-pass estimate by 2.5. That's the historical accuracy ratio for rewrite estimates of working apps.
- Add parallel costs. What does it cost to keep the original app alive during the rewrite? Multiply by months.
- Add discovery costs. What does it cost to rediscover the edge cases? Most teams budget 0 for this. The real number is 2–6 months of bug fixes post-cutover.
- Compare the totals. If the rewrite is still cheaper, you may have a genuine case. If it's 3–5x more expensive, you have an upgrade.
Want a fixed-price number on the upgrade side?
We quote React Native upgrades against a fixed scope and a fixed timeline. Run the scanner against your lockfile and we can quote a real number — the comparison vs a rewrite gets easier when one side stops being a multi-quarter unknown.
Frequently Asked Questions
Is it cheaper to rewrite an app in Flutter or upgrade React Native?
Almost always cheaper to upgrade. A React Native upgrade from a multi-year-behind version usually runs 4–12 weeks of focused engineering. A full rewrite of a non-trivial production app in Flutter runs 6–18 months and reintroduces every bug you've fixed over the original app's lifetime. The exceptions are small apps with low edge-case complexity, apps where the team genuinely wants to abandon React Native for non-technical reasons, or apps where multi-platform requirements have changed in ways React Native can't follow.
Does Flutter perform better than React Native?
On synthetic benchmarks, Flutter has historically edged out React Native on rendering, especially for highly custom UI. After the React Native New Architecture (Fabric, TurboModules, Bridgeless) landed and became default, the gap narrowed significantly. For most app workloads — list rendering, navigation, network-backed screens — the difference is not perceptible to users. Performance is rarely the right reason to rewrite a working app.
What are the hidden costs of rewriting an app?
Lost edge-case coverage is the big one. Every fix and tweak shipped over the app's lifetime represents a bug, a customer complaint, or a regression that won't be in the rewrite by default. Other costs: parallel feature development on the old codebase during the rewrite, team retraining or new hires for the new stack, lost test coverage, lost analytics and monitoring continuity, App Store / Play Store transition risk, and lost institutional knowledge as engineers leave during a long rewrite.
When does rewriting in Flutter make sense?
Three honest cases. First, the app is small enough that a rewrite is genuinely shorter than the upgrade backlog — usually means under 50 screens, light native integration, simple data flow. Second, business requirements have shifted to something React Native can't serve well — for example, a complex graphics or game-like UI where Flutter's rendering model genuinely fits better. Third, the team has reached a stable consensus that React Native isn't the right long-term platform for non-technical reasons (hiring market, internal Dart investment, strategic alignment). "We're behind on upgrades" is not a reason to rewrite.
How long does a Flutter rewrite of a React Native app take?
For a real production app — meaning more than 30 screens, a real backend, analytics, payments, push notifications, deep links, accessibility, internationalization — plan on 6 to 18 months. The variance is mostly the long tail: re-implementing every edge case, getting back to feature parity, validating that the rewrite doesn't regress conversion rates or crash rates. Engineering estimates almost always undercount the long tail.
Can I migrate from React Native to Flutter incrementally?
Technically, yes — Flutter supports being embedded as a module inside an existing native app, and you can wrap that in React Native or run it side-by-side. Practically, it's awkward. You end up maintaining both stacks, plus the bridge between them, plus duplicate state management. Most teams that attempt incremental migration end up doing a hard switch anyway after several months of friction. Pick one strategy and commit.