Native, Flutter, React Native, KMP or Web: How to Choose
Choose the stack your product needs, then check your team can own it.
For founders, product leaders and engineering leaders deciding how to build an app across iOS, Android and the web.
Updated , by A Few Good Coders
Published 13 min read11 sectionsWhite paper
Key takeaways
- No option wins everywhere: native leads on platform depth, Flutter and React Native on shared UI, Kotlin Multiplatform on shared logic under native UI, and the web on reach and discoverability.
- Hard constraints such as widgets, watch apps, background Bluetooth or search indexing should rule options out before any weighted scoring begins.
- Team skills and long-term ownership often move the result more than raw performance, so weight them honestly.
- The hidden costs of cross-platform sit at the edges: plugins, platform channels, app size, accessibility of custom UI and web limitations; native's hidden cost is drift between two apps.
- Scores within about 10% of each other are a tie, best settled by a two-week vertical slice on real devices rather than a debate.
The short answer
Pick the option whose weaknesses your product can live with. Native (Swift and Kotlin) is the default when platform features lead the product. Flutter and React Native fit when most behaviour and UI are shared across iOS and Android. Kotlin Multiplatform fits when you want native UI over shared business logic. The web, including a progressive web app (PWA), fits when reach, links and search matter more than deep device access.
We build with Flutter often, and it is one of our services, but a stack chosen for the vendor's convenience costs the client for years. So this guide treats every option on its merits, names the costs each one hides, and ends with a worksheet you can fill in with your own team. Three rules run through it:
- Constraints before preferences. An Apple Watch app or background Bluetooth decides more than any score.
- The team is part of the stack. A framework your team cannot hire for or maintain is the wrong one.
- Decide with evidence. When the options are close, build a thin slice and measure it.
The five options, defined
Each option trades how much code is shared against how close it sits to the platform. The table reflects October 2026; check current release notes before you commit.
Two terms matter for the rest of this guide. A platform channel is the bridge a cross-platform framework uses to call native code it does not wrap itself; Flutter calls these method channels and React Native calls them native modules. A PWA is a website that can be installed to the home screen and work offline through a service worker. What a PWA can do depends on the browser, and iOS is the most restrictive: Safari supports web push only for web apps the user has added to the home screen.
All five are mainstream production choices. Kotlin Multiplatform has been stable since late 2023, and JetBrains declared Compose Multiplatform stable on iOS in 2025. React Native's New Architecture is now the default for new projects. The decision is about fit, not maturity.
The decision criteria
Seven criteria decide most stack choices. Score your product against each before you look at frameworks, because the product's shape is what makes an option cheap or expensive.
Three notes on reading the table honestly.
Performance is rarely the deciding criterion. Most business apps are lists, forms, media and network calls, and every option here handles those well when engineered carefully. Performance decides the stack when the product does sustained custom rendering, heavy on-device computation or real-time audio and video. Then, prototype the hard screen on each candidate rather than trusting anyone's benchmark, including ours.
Platform-specific UX is a product decision. A financial app with a strong brand may want the same UI everywhere; a utility that sits next to system settings may want to look exactly like the OS. Decide which you are before a framework decides for you.
Hiring cuts both ways. A larger pool helps with replacement; a smaller one can be easier to screen. What really hurts is a stack only one person on the team understands.
When Flutter is the right call
Flutter is the right call when most of the product is shared journeys, one brand UI matters, and one team needs to ship to several platforms at the same rhythm. It is weaker when the product's value lives in platform features.
Signals that point to Flutter:
- The journeys are the product. Onboarding, accounts, catalogues, workflows, payments and dashboards: behaviour that should be identical on iOS and Android.
- One consistent UI is a feature. Flutter draws its own widgets, so a custom design system looks and behaves the same on every device, including older OS versions.
- More than two screens are on the roadmap. Official web, Windows, macOS and Linux targets let a tablet or desktop companion reuse the domain logic and design system.
- A small team owns everything. One codebase, one test suite and one release train are easier for four engineers to carry than two native apps.
Two products we have worked on show the shape. For BankSathi, we built the Flutter application architecture and the advisor journeys for product discovery, lead management, conversion tracking and payouts, shipped as production Android and iOS apps. For ScoreUp, we delivered the Flutter product across credit report visibility, guided explanations and next-action journeys, maintained on a shared Flutter foundation with a live Android release. Both are workflow products whose value lives in journeys that should behave identically for every user, not in hardware features. That is where a shared codebase earns its keep.
Flutter does not make a product cheaper by default. It removes duplicated work when the work is genuinely shared; platform-specific work is paid for in native code either way, plus the bridge.
When Flutter is not the right call
Flutter is the wrong default when platform features lead the product, when it must be found through search, or when the team's skills and hiring plan point elsewhere. In each case another option is simply a better fit.
None of these is a rule against Flutter. A product can be mostly shared journeys with one platform-led feature, and the answer is then often Flutter plus a native module at a narrow boundary. The skill is noticing when the exception has become the product.
A scoring worksheet you can use
Use the worksheet in two passes: rule options out with hard constraints, then score what is left. It takes an afternoon with the product lead and two engineers.
Pass 1: vetoes. Answer yes or no. Any yes can remove an option outright.
- Does the product need a home-screen widget, watch app, CarPlay or Android Auto in its first year? (Plan native UI for that surface in any stack.)
- Does it need background Bluetooth, background location or continuous sensor access on iOS? (Rules out a PWA.)
- Must its pages be indexed by search engines or open instantly from shared links? (Rules out Flutter web and app-only options for those pages.)
- Must the new work live alongside an existing app that already has users? (Favours incremental routes: Flutter add-to-app, React Native in an existing app, or a KMP module inside it.)
- Is there a regulatory or contractual accessibility requirement? (Make it a prototype test for every option.)
Pass 2: weighted scores. Give each criterion a weight from 1 (barely matters) to 5 (decides the product). Then score each surviving option from 1 to 5: 5 means a strong fit with no workaround, 3 means workable at a known cost, 1 means you would be fighting the option. Multiply weight by score and add up each column.
Weighted score = Σ (criterion weight × option score)
Here is an illustrative example: a hypothetical booking product with a consumer app on iOS and Android and a staff dashboard on the web, built by three engineers with React and TypeScript experience and one with Kotlin. The numbers are invented to show the method, not a verdict on any framework.
Three things to notice:
- Team skills moved the result. Give the same product a team with Flutter experience and Flutter's team-skills score rises from 3 to 5, adding 8 points and taking it to 92. The product did not change; the people did.
- Close scores are a tie. Flutter at 84 and the web at 85 are indistinguishable. Treat anything within about 10% of the leader as a candidate worth testing.
- Vetoes still apply. If the booking product depends on reliable reminders on iOS, the PWA's reliance on users installing it to the home screen for web push may rule it out whatever it scores.
Keep the filled-in worksheet with the project's decision records, so the answer to "why is it built this way?" is a document, not a memory.
Hybrid and migration paths
The choice is rarely all or nothing. Most mature products end up hybrid, and every mainstream option supports incremental adoption. Choose the path that keeps the decision reversible.
- Flutter add-to-app. Embed Flutter screens in an existing native iOS or Android app, one journey at a time. It is a low-risk way to test Flutter on a real feature before committing the product.
- React Native in an existing app. The same idea: a native shell, with React Native screens where they help.
- KMP inside native apps. Move networking, validation and business rules into a shared Kotlin module while both native UIs stay as they are. Often the cheapest way to stop drift between two native apps.
- Native modules at a narrow boundary. In a Flutter or React Native app, keep platform-led features such as a widget, a camera pipeline or a payments SDK in native code behind one well-defined interface.
- Split by surface. Server-rendered web for marketing and content, a cross-platform or native app for the signed-in product, and one API behind both.
Avoid the big-bang rewrite if you can: it pauses the roadmap while users keep filing bugs against the old app, whereas incremental paths keep shipping while you learn whether the new stack holds up. Our guide to taking over a codebase covers how to assess an existing app before you decide.
Run the decision in two weeks
When the worksheet produces a close call, build a thin vertical slice in the top two candidates and measure it. Two weeks of evidence costs less than two years of regret.
A useful slice is one real journey, not a demo:
- Pick the riskiest journey. Usually sign-in plus the screen with the hardest device integration or the heaviest rendering.
- Use real infrastructure. Real authentication, the real API, real analytics, and a build pipeline to TestFlight and the Play internal testing track.
- Test on the devices your users own. Include an older, lower-end Android phone, not only the team's flagships.
- Measure what the worksheet guessed. Cold start, smoothness on the heaviest list, build size, screen-reader behaviour, and how long the device integration took to get working.
- Ask the team. Which codebase would they rather be maintaining in a year, and why?
Update the worksheet with what you measured, make the call, and note what would make you revisit it.
If you want a second opinion, tell us about the product. We start with a call on fit and risk. If Flutter is the right tool, our Flutter app development work begins with one complete journey released in a bounded first milestone; if it is not, we will say so. Once you have chosen, our guide to architecture that survives year two covers what to build next.
Questions
Is Flutter cheaper than building two native apps?
It can be, but only for the work that is genuinely shared. Shared journeys, UI and logic are built and tested once, while platform-specific features still need native code and plugins add maintenance. Estimate how much of your roadmap is identical across platforms before assuming any saving.
Should we choose Flutter or React Native?
Both are mature and share most code across iOS and Android. Flutter draws its own UI, which suits one consistent brand experience and extends to web and desktop targets. React Native uses native platform controls and fits teams with strong React and TypeScript skills. Team skills and UI goals usually decide it more than performance does.
Is Kotlin Multiplatform ready for production?
Kotlin Multiplatform has been stable since late 2023 and is used to share business logic between Android and iOS while keeping native UI. Compose Multiplatform adds optional shared UI and was declared stable on iOS in 2025. It fits best when the team already knows Kotlin; check library support for your specific needs, as of October 2026.
Can a progressive web app replace a native app?
For many content, booking and internal tools, yes: a PWA can be installed, work offline and update without store review. It falls short when the product needs deep device access, background work or dependable push on iOS, where web push requires the user to add the app to the home screen first. Run the veto questions before choosing it.
Is Flutter good for building websites?
Flutter web is a good fit for signed-in, app-like tools such as dashboards and internal workflows that share code with a mobile app. It is a poor fit for marketing or content sites that need fast first paint and search indexing, because it renders into a canvas rather than ordinary HTML pages. Many products pair a Flutter app with a separate web stack for public pages.
Should we rewrite our native app in Flutter?
Only if the evidence supports it. Measure how much of the roadmap is shared, then try Flutter's add-to-app on one real journey inside the existing app. If drift between two native apps is the real problem, sharing logic with Kotlin Multiplatform may fix it with less disruption.