Every mobile project starts with the same argument, and most of the writing about it is vendor advocacy. The honest answer is that all three options are good, they fail in different places, and the right choice depends on facts about your specific project that are knowable in about an hour.
Here is the procedure we use.
Start with the three overrides
Before comparing anything, check whether one of these applies. If it does, the decision is made and the rest of the analysis is theatre.
Override 1: the app is mostly a wrapper around platform capability. Deep camera control, CoreML or on-device inference, HealthKit, background audio, complex Bluetooth, widgets, Watch or Wear integration, share extensions. If your app's value is the platform integration, go native. You will spend more time writing and maintaining bridges than you saved by sharing code, and you will hit the newest APIs a release cycle late, every cycle.
Override 2: you have an existing team with an existing skill set. A team of four strong React engineers will ship a better React Native app in three months than a better-in-theory Flutter app in six. Team fit beats framework merit at almost every realistic project size. The exception is if you are hiring specifically for this project, in which case the constraint is the local hiring market — which for mobile in most Australian cities means more React Native and native people than Flutter people.
Override 3: the app must feel like a system app. If your users will compare it directly to Mail, Files, or their bank's native app — where every scroll deceleration and sheet transition is being judged against the platform's own — go native. Both cross-platform frameworks get close now. Close is not the same as indistinguishable, and some products are held to that standard.
If none of those apply, keep reading.
Then compare on the things that actually differ
Rendering model
Flutter draws every pixel itself with its own engine. React Native maps to real platform views.
That difference explains most of the downstream trade-offs. Flutter gives you pixel-identical rendering across platforms and versions, which is excellent for a heavily branded UI and awkward when you want native behaviour you did not explicitly implement — text selection menus, accessibility affordances, the way a scroll view behaves at its bounds. React Native gives you native behaviour for free and, in exchange, small platform inconsistencies you will spend time reconciling.
Neither is better. They are different defaults about who owns the last five percent.
Where the performance cliff is
For ordinary applications — lists, forms, navigation, network calls — both are fine. Anyone who tells you React Native is slow is describing 2018.
The cliffs are specific. React Native struggles with sustained high-frequency work crossing the JS boundary, though the new architecture has improved this considerably. Flutter struggles with very large images and has a heavier baseline app size. If you have a genuinely animation-dense product, prototype the hardest screen in both before committing. A week of prototyping is cheap against a year of building on the wrong foundation.
Ecosystem shape
React Native's ecosystem is broader and shallower: there is a package for almost everything, and quality varies enormously. You will evaluate dependencies carefully and you will occasionally maintain a fork.
Flutter's is narrower and deeper: fewer packages, more of them first-party and well-maintained. You will more often find nothing exists and write it yourself.
Both are workable. They demand different kinds of vigilance.
The realistic code-sharing number
Marketing says 90%. In our experience it is 70–85% for a typical app, and the remainder is not evenly distributed — it concentrates in exactly the places that are hard: permissions, deep links, push notifications, in-app purchases, background execution, and anything touching the platform's privacy model.
Budget for it. A plan built on 95% sharing goes wrong in month three, and it goes wrong in the fiddliest possible areas.
Where we land, in practice
- Content, commerce, social, internal tools, most SaaS companions → React Native, especially with an existing React web codebase and shared types.
- Heavily branded, animation-rich, design-led products where visual consistency matters more than platform idiom → Flutter.
- Platform-capability-led apps, or products judged against system apps → native Swift and Kotlin.
- One platform first, with real uncertainty about the second → native. Do not pay the cross-platform tax for a second platform you might never build.
The question nobody asks first
Does this need to be an app at all?
A responsive web application, installable as a PWA, ships to every platform at once with no review queue and no store fees. It is the right answer more often than the mobile industry likes to admit — and it is the wrong answer the moment you need push notifications on iOS, real offline capability, or presence on the App Store as a distribution channel.
We ask this one first. Occasionally it saves a client the entire project.
Weighing up a mobile build? Tell us what you are trying to make and we will give you a straight recommendation, including if that recommendation is "not an app".