Choosing a mobile stack

How to choose a mobile stack that drives user conversion and revenue

Choose a mobile stack by scoring native, cross-platform and web-wrapper options on time to release, release cadence, cost per feature and time to fix.

15 min read

Quick answer

Choosing a mobile stack comes down to four business outcomes: time to first release, release frequency after launch, the cost to ship the same feature on iOS and Android, and how quickly you can fix what breaks in production. Score every option on those before you argue about languages. Native gives maximum platform control. A shared codebase gives you one team, one release train and a lower cost per feature.

Why does the mobile stack decision matter?

You hired an iOS engineer because your first customer used an iPhone. Eight months later the Android build is "next quarter" for the third time, half the sales pipeline is on Android, and that iOS engineer is the only person who can ship a fix. Nobody chose the stack. It came with the first hire, and nobody has revisited it since.

The other version of the story is the enterprise that picked native for both platforms in 2019 and now runs two teams, two backlogs and two release calendars for one product. Every feature is estimated twice. The Android version of a checkout change ships three weeks after iOS, and the growth team cannot run a clean experiment because the two apps never match.

Both teams treated the stack as an engineering preference instead of a decision with a revenue line attached. Score every option against the four outcomes below, then compare what native, cross-platform and web-wrapper stacks do to each.

Which outcomes should decide your mobile stack?

1. Time to first release. The day your app is in both stores is the day conversion starts. For a two-platform launch, the useful question is how fast you can ship both apps, since one team shipping one app only gets you halfway.

2. Release frequency after launch. Apps that ship weekly learn weekly. Apple says that 90% of App Store submissions are reviewed in under 24 hours, so review is rarely the bottleneck. The bottleneck is how many separate builds, test passes and sign-offs one change needs before it reaches users. Two codebases means two of everything.

3. Cost to ship the same feature on iOS and Android. If a feature costs 10 engineer-days on iOS and another 10 on Android, the stack has doubled the price of every roadmap item. If it costs 10 days plus 1 day of platform-specific work, the stack has paid for itself.

4. Time to fix what breaks. A crash in checkout is a revenue leak measured per hour. The relevant numbers are how long it takes to get a fix into a build, through review, and onto devices. Both stores support staged rollouts. Apple's phased release moves from 1% of users on day one to 100% on day seven. Google Play lets you pick a rollout percentage and halt it if a problem appears. Some stacks can also update the JavaScript bundle between store releases, within the limits of App Store Review Guideline 2.5.2, which we come back to below.

Raw frame rate and binary size are not on the list. They matter when they are bad enough to hurt conversion, and below that threshold they do not show up in the P&L.

How do native, cross-platform and web-wrapper stacks compare?

Native (Swift and Kotlin)

Two codebases, two teams, full access to every platform API on the day Apple or Google ships it. Time to first release on both platforms is the sum of two projects unless you can staff both in parallel. Release frequency is bounded by the slower team. Cost per feature is close to double. Time to fix is a store release, since native binaries cannot be patched over the air.

Native wins for platform-first design teams that want the two apps to behave differently on purpose, for heavy 3D and camera pipelines, and for apps where a 100 ms startup difference is the product. Shopify, which reported sub-500 ms P75 screen loads and over 99.9% crash-free sessions on React Native in January 2025, announced in September 2026 that it is moving its apps back to Swift and Kotlin. Its rewritten Shop app cut iOS startup from 3,200 ms to 2,466 ms and Android startup from 4,433 ms to 2,233 ms. That is a real win. The rewrite took six senior engineers 12 weeks, using a purpose-built agent workflow.

Cross-platform frameworks with a shared codebase

Flutter, Kotlin Multiplatform and React Native are the three main options, listed here alphabetically, and they are not interchangeable.

Flutter compiles Dart to machine code and draws every pixel with its own engine, Impeller, instead of using the platform's widgets, as the Flutter architectural overview explains. That gives pixel-identical UI on both platforms and strong performance for custom, animation-heavy interfaces. Where it wins over React Native: design systems that deliberately ignore platform conventions. Where it loses: every new iOS or Android control has to be reimplemented in Dart, and Dart is a smaller hiring pool than JavaScript.

Kotlin Multiplatform (KMP) shares business logic in Kotlin while the UI stays native, or shares the UI too through Compose Multiplatform, which JetBrains lists as stable on Android, iOS and desktop. Where it wins: an existing Android team that wants to share networking, models and validation with iOS without giving up native UI. JetBrains' own comparison with React Native says a JavaScript-experienced team "may find React Native to be a practical choice". Where KMP loses: the shared-logic model still leaves you writing two UIs, so cost per feature drops less than with a shared-UI stack.

React Native runs JavaScript or TypeScript that drives the platform's own UI components. A <View> becomes a UIView on iOS and a ViewGroup on Android, per the React Native docs on core components. The output is a native binary. Because the application logic is JavaScript, that layer can be updated between store releases. Where it wins: web and TypeScript teams that want platform UI from one codebase. Where it loses: custom rendering pipelines, and teams with no JavaScript experience.

Web wrappers (Capacitor, Ionic)

A web wrapper is a web app packaged in a native shell and rendered in a web view, with native APIs reached through plugins, as the Capacitor docs describe. Time to first release is excellent if the web app already exists, and cost per feature is the lowest of any option. Where it loses: scrolling, gestures and animation run in a browser engine instead of platform views, and users can tell. Web wrappers suit a content app or an internal tool. For a consumer app where conversion depends on feel, measure it before you commit.

How do the stacks score on the four outcomes?

OutcomeNative (Swift, Kotlin)FlutterKotlin MultiplatformReact NativeWeb wrapper (Capacitor, Ionic)
Time to first release on both platformsTwo projects; parallel only if you staff two teamsOne project, one teamOne shared logic project plus two UI projectsOne project, one teamOne project, reusing the web app
Release frequency after launchBounded by the slower of two teamsOne release trainOne logic train, two UI trainsOne release trainOne release train
Cost to ship a feature on both platformsRoughly 2x~1x plus platform-specific workBetween 1x and 2x depending on UI sharing~1x plus platform-specific work~1x
Time to fix in productionStore release, staged rolloutStore release (Dart is compiled; no equivalent OTA path in the framework)Store releaseStore release, or JavaScript bundle update between releasesStore release, or web content update
Platform UI fidelityHighestConsistent across platforms, not platform viewsHighest with native UI; consistent with Compose MultiplatformHigh (platform views)Lowest (web view)
Best forPlatform-first design, heavy 3D, ARCustom, animation-heavy design systemsAndroid-first teams sharing logic with iOSWeb-skilled teams, one codebase, OTA JavaScript fixesExisting web apps, internal tools

Sources: React Native docs, Flutter docs, Kotlin Multiplatform, Capacitor docs, Apple phased release, Google Play staged rollouts.

How does hiring affect your choice of mobile stack?

The stack decision is a hiring decision. Whoever you can recruit in six months is the team that will maintain this app for six years.

The 2025 Stack Overflow Developer Survey reports that 66% of all respondents used JavaScript in the past year and 43.6% used TypeScript. Kotlin was 10.8%, Dart 5.9% and Swift 5.4%. That is a pool-size ranking, not a quality ranking, and it says the JavaScript pool is roughly twelve times the Swift pool.

The most recent Stack Overflow data that lists mobile frameworks is the 2024 survey: Flutter 9.4%, React Native 8.4%, .NET MAUI 3.1%, Ionic 2.5%, Capacitor 1.8%. Flutter and React Native are close in developer count. They differ in where the developers come from. A React Native hire is usually a web engineer who already knows React, while a Flutter hire has learned Dart for Flutter.

Store data adds a second angle. Appfigures found that apps built with React Native or Flutter made up 15% of new app releases in 2024, up from 7% in 2020. In its October 2024 breakdown, Flutter had the larger share of new releases (11.07% against 6.75%) while React Native apps produced slightly more net revenue in the trailing 30 days ($287M against $283M) and had more apps earning over $1M (173 against 37). Flutter is more common in the long tail; React Native is more common at companies with revenue.

Team shape matters more than the framework name. Coinbase reported that in mid-2020 it had about seven Android engineers and eighteen iOS engineers, and that the imbalance held the Android app back. After moving both apps to React Native in January 2021 the same engineers worked on one codebase. incident.io shipped a production mobile app without hiring any additional engineers, with custom native work at about 2% of the effort, because its product engineers already wrote TypeScript.

Do AI coding agents change which stack you should pick?

They do, in both directions. The 2025 Stack Overflow survey found that 84% of developers use or plan to use AI tools, and that only 3.1% "highly trust" the output. Both numbers matter for this decision.

The argument for native is that agents lower the cost of writing a feature twice. Shopify made exactly this case in its September 2026 post on going back to native: coding agents "could implement a feature on Android using the iOS version as reference, and vice versa," which Shopify says cut the cost of keeping the two platforms at parity. If that holds for your team, outcome 3 (cost per feature) narrows between native and cross-platform, and native's platform control starts to win on the remaining outcomes.

The argument for a shared JavaScript codebase is about what agents are good at. GitHub's Octoverse 2025 report recorded that in August 2025 TypeScript became the most used language on GitHub by contributor count, with JavaScript third at 2.15 million contributors, and noted that TypeScript's "types work well with AI coding tools". A model has seen far more React than SwiftUI. One codebase also means one place for an agent to make a mistake and one test suite to catch it, instead of two codebases kept in sync by a tool that 66% of developers say produces answers that are "almost right, but not quite," according to Stack Overflow's 2025 AI survey.

Neither argument is settled. Shopify built a dedicated agent workflow and concluded native. If your team has no comparable workflow, the arithmetic of one codebase still holds. Decide with your own numbers: how many engineers, what they already write, and how much of your roadmap is platform-specific.

Where Expo fits

Expo is the open-source framework for React Native that the React Native team, in its June 2024 announcement, called the only recommended community framework. It is the way Meta recommends everyone build with React Native. The framework is free and MIT-licensed. Expo Application Services (EAS) is the optional paid cloud layer for builds, store submission and updates.

Here is what Expo changes for a React Native team, outcome by outcome.

Time to first release. A new project starts with one command and does not require Xcode or Android Studio on the developer's machine, because Continuous Native Generation generates the native projects at build time from app.json and EAS Build compiles them in the cloud.

Release frequency. One codebase, one build command for both stores, and EAS Submit for upload. MyWheels reported moving from a three-week release cycle to weekly releases after adopting Expo.

Time to fix. EAS Update publishes a new JavaScript bundle and assets to installed apps, with percentage-based rollouts and a revert command. An update changes only the JavaScript and assets. It does not change native code, permissions or the app binary, and it does not bypass store review: your updates must follow the same store guidelines as the original app, including App Store Review Guideline 2.5.2.

MTA's TrainTime team (about 20 people, roughly 350K daily users) says it can identify, patch and deploy an OTA fix in under 90 seconds from the first user report.

Companies that name their React Native use in public include Microsoft (Office, Outlook, Teams), Amazon (Shopping, Alexa) and Meta (Facebook, Ads Manager) on the React Native showcase, plus Coinbase and Bluesky, which builds on Expo. Expo's customer pages name MTA, Hipcamp, Phantom, Partiful, incident.io and Mollie among others.

Limitations

Expo does not close the startup-time gap to a well-built native app. It does not remove the need for native code when you need a platform API no library exposes; you write a module in Swift or Kotlin with the Expo Modules API. Expo Go, the sandbox app, is a playground and not for production; real projects use development builds. Pricing: the Free plan includes 15 Android and 15 iOS cloud builds a month and updates for 1,000 monthly active users; Starter is $19 a month and Production is $199 a month, with usage-based overages.

Which mobile stack should you choose?

If your situation isLean towardBecause
Custom design system, animation-heavy, no interest in platform conventionsFlutterOwn rendering engine, pixel-identical output
Established Android team, iOS app must stay fully nativeKotlin MultiplatformShare logic, keep both UIs native
Platform-first design, heavy 3D or AR, two teams already fundedNativeFull platform control, no framework layer
Web or TypeScript team, both platforms, consumer appReact NativeOne team, platform UI, JavaScript fixes between releases
Existing web app, internal tool, budget is the constraintWeb wrapperLowest cost per feature
Six senior engineers and a mature agent workflow, parity cost is the only reason you shared codeReconsider native, as Shopify didAgents lower the cost of writing twice

Next step

Write down your answer to the four outcomes for the next twelve months: platforms at launch, release cadence, which languages you can hire, and how long a checkout bug can stay live. If the answer points to a shared codebase with a JavaScript team, start with the Expo getting started guide. If it points to Flutter or Kotlin Multiplatform, the Flutter architectural overview and JetBrains' KMP page are the places to start.

Verified on 12 September 2026.

Keep reading

Frequently Asked Questions