Why the stack decision matters more than the stack
Most teams ask "which framework is best?" The more useful question is "which framework fails least for this product over the next five years?" Every option on this page can ship a good app. Each one also has a predictable place where it gets expensive: a native SDK with no maintained plugin, a UI that has to look exactly like iOS, a team that only knows one language, or a release cadence that can't absorb framework upgrades.
Our job in cross-platform mobile app development is to find those pressure points before you commit. We look at your feature list, your existing engineers, your backend and your roadmap, and then recommend an approach. Sometimes that recommendation is two native apps. We would rather tell you that up front than discover it in month six.
Native vs Flutter vs React Native vs Kotlin Multiplatform
The four approaches differ mainly in what they share. Flutter and React Native share UI and business logic. Kotlin Multiplatform (KMP) shares business logic by default and lets you choose whether to share UI with Compose Multiplatform. Fully native shares nothing except your backend and design system.
| Factor | Native (Swift / Kotlin) | Flutter | React Native | Kotlin Multiplatform |
|---|---|---|---|---|
| Language | Swift on iOS, Kotlin on Android | Dart | TypeScript / JavaScript | Kotlin, with Swift for iOS UI if not sharing UI |
| What is shared | Nothing in the app layer | UI and logic | UI and logic | Logic by default; UI optional |
| UI rendering | Platform UI toolkits | Own rendering engine | Platform native views | Native UI, or Compose Multiplatform |
| Platform look and feel | Exact by default | Custom by default; platform styles need work | Close to platform by default | Exact when UI stays native |
| New OS APIs | Available on release day | Via plugins or platform channels | Via native modules | Direct from Kotlin/Swift interop |
| Best fit | Hardware-heavy or platform-flagship apps | Brand-led UI, fast iteration on both stores | Teams with React and TypeScript skills | Existing Android/Kotlin teams, complex shared logic |
If one of these is already the obvious fit, our Flutter delivery team and React Native engineers cover each framework in more depth.
A decision framework you can run in a week
We run this as a short paid assessment or as the first week of a project. You get a written recommendation with the reasoning, not just a framework name.
- 1
List the platform-dependent features
We tag every feature as UI-only, logic-only or OS-dependent. OS-dependent items (push handling, background tasks, payments, health data, Bluetooth, NFC, CarPlay or Android Auto) get extra scrutiny.
- 2
Check plugin and SDK coverage
For each third-party SDK you need, we check whether an official or well-maintained package exists for each framework, how recently it was updated, and how many open issues it carries.
- 3
Map your current team
A web team strong in React points one way; an Android team fluent in Kotlin points another. Hiring around the existing skill base is usually cheaper than retraining.
- 4
Prototype the riskiest screen
We build the hardest interaction, such as a map with live tracking or a camera flow, in the leading candidate and measure frame rate, startup time and memory on mid-range devices.
- 5
Project the five-year cost
We estimate upgrade effort, the native work that will remain, and the team you would need to keep the app healthy after launch.
What is shared in cross-platform apps, and what isn't
Vendors sometimes quote "95% code reuse." The real number depends on your app, and it is rarely the number that matters. What matters is where the unshared code lives and who maintains it.
Usually shared
Screens and navigation (Flutter, React Native), API clients, data models, validation, state management, business rules, analytics event definitions, localization strings and most tests for logic.
Often partly shared
Push notification handling, deep links, in-app purchases, maps and media playback. A package covers the common path, but edge cases need platform code.
Rarely shared
Home screen widgets, App Clips and Instant Apps, watch and TV apps, share extensions, Live Activities, accessibility tuning, and anything that needs a new OS API in its first months.
Never shared
Store listings, signing certificates and provisioning, privacy declarations for each store, release review processes, and platform-specific QA on real devices.
Plan for some Swift and Kotlin in any cross-platform project. A team with no native depth will stall the first time a plugin breaks after an OS update.
Performance and native-feature trade-offs
Rendering and smoothness
Flutter draws its own UI, which gives consistent visuals across devices and smooth custom animation, but means platform controls are recreated rather than reused. React Native renders real platform views, and its newer architecture reduces the overhead of the old JavaScript bridge. Native and KMP-with-native-UI have no extra rendering layer at all. For typical business apps (forms, lists, dashboards) users will not notice a difference. For heavy animation, long scrolling lists with media, or real-time graphics, profile on low-end Android devices before deciding.
App size and startup
Flutter and React Native both add a runtime to the app bundle, so a minimal app is larger than its native equivalent. This rarely blocks a launch, but it matters in markets with expensive data or for App Clips and Instant Apps with strict size limits.
Access to new platform features
When Apple or Google ships a new API, native code can use it immediately. Cross-platform frameworks need a plugin or a custom bridge. Our native iOS team and Android specialists write those bridges when your roadmap needs a feature before the community catches up.
Team composition for each approach
The framework decides who you need on the team. These are typical shapes for a product in active development; we adjust them to your scope.
| Approach | Core engineers | Supporting skills |
|---|---|---|
| Two native apps | Separate iOS and Android developers, often in parallel | Shared QA, design system owner, backend |
| Flutter | Dart/Flutter developers working across both platforms | Part-time iOS and Android engineer for plugins and release issues |
| React Native | TypeScript/React Native developers | Native module experience on both platforms; web developers can contribute to shared logic |
| Kotlin Multiplatform | Kotlin developers for shared modules and Android | Swift developer for iOS UI unless Compose Multiplatform is used on iOS |
Every option still needs QA on real iOS and Android devices. Cross-platform does not halve testing, because each store build behaves differently on its own operating system.
Long-term maintenance of a shared codebase
The cost of a framework shows up after launch. Each year brings a new iOS and Android release, framework upgrades, and plugin updates that may lag behind. Before you commit, decide who will own that work.
- Framework upgrades: Flutter and React Native ship frequent releases. Skipping several makes the eventual upgrade much harder, so we schedule upgrades rather than letting them pile up.
- Plugin risk: A community package that loses its maintainer becomes your code. We prefer official or widely used packages and keep a list of fallbacks.
- Hiring: Check the local and offshore talent pool for your chosen stack. A niche choice can make backfilling an engineer slow.
- Exit options: KMP lets you share less over time without a rewrite. Flutter and React Native allow embedding native screens, which gives you a gradual path out if you ever need one.
Our maintenance and support service covers this upgrade work for apps we build and for apps built by other teams.
How a cross-platform engagement runs with us
After the stack decision, delivery follows two-week sprints with a demo build on both platforms at the end of each sprint. You get TestFlight and Play internal testing builds, a shared backlog, and direct access to the engineers. We set up CI pipelines that build, test and sign both apps from the same commit, so platform drift is caught early rather than at release time.
If you already have a native app and want to share some code without rewriting, that is possible too: Flutter modules, React Native screens and KMP libraries can all be added to an existing native project. Tell us about your app and we will suggest a starting point.