In June 2018 Airbnb published a five-part engineering series explaining why it was sunsetting React Native after two years. That series is still the most-cited evidence in any debate about cross-platform app development frameworks, usually as proof that sharing one codebase across iOS and Android breaks down at scale. Two years later Shopify went the other way and made React Native its default for new mobile apps. Both companies had strong engineers and good reasons. What separated them was the shape of the problem each one was solving.
Airbnb was fitting React Native into large, mature native apps. Its engineers ended up working across three environments at once (Swift, Kotlin and JavaScript), with bridge code joining them and a team split down the middle. Shopify was building new apps whose value sat mostly on its servers. My position after 11 years of shipping mobile products follows from that difference. A cross-platform framework should be your default for any app whose value lives on the server or in the workflow. Native should be your choice when the value lives in the device. The savings are real but smaller than the pitch, and that is fine, because the case for cross-platform never depended on the 50% figure.
The Pitch Is Half the Cost. The Arithmetic Says About a Fifth.
The usual claim is simple: one codebase instead of two, so half the cost. That only holds if the mobile client is the whole project. It rarely is. On a typical mid-complexity consumer or marketplace app, the two native clients together make up about half the budget. The rest goes on the backend and admin tools (around a quarter), design, QA, DevOps and project management.
One shared codebase usually costs 60-70% of two native ones, not 50%. You still write platform-specific code for navigation conventions, permissions, push notifications, payments sheets and store requirements, and that takes 15-25% of the client effort. You still build or maintain native modules for anything the framework doesn't cover. And QA still tests on real iPhones and real Android devices, because "it compiles for both" and "it works on a Samsung with an aggressive battery manager" are different claims. The backend doesn't shrink at all.
Put those together and cross-platform saves roughly 15-25% of the total build. On a $100,000 product, that's $15,000-25,000. It's a real number and worth having. It's also smaller than the gap between a disciplined scope and a loose one. When we rescued the stalled Meal4U build, we spent a week taking the scope apart and re-estimated it about ten times, cutting 30-50% on each pass until we reached the smallest product worth shipping. Choosing a framework adjusts a budget. Cutting scope decides whether the product ships at all.
Side by Side: One Shared Codebase vs Two Native Apps
The comparison that matters is between React Native or Flutter and Swift plus Kotlin, scored on four axes: control, cost, speed and risk. On three of the four, cross-platform wins for the typical business app. The fourth axis is where the whole decision gets made.
Control
Native wins on control, and the gap is specific, not vague. New iOS and Android APIs appear in Swift and Kotlin on day one. Framework support comes later, sometimes weeks and sometimes much longer, depending on whether someone in the community writes the binding. Some surfaces never leave native at all. iOS home-screen widgets and Live Activities have to be written in SwiftUI whichever framework you use. Android widgets are native too. Watch apps are native. If your roadmap includes any of these, your "single codebase" already has native code in it. That's workable, but you should plan for it on day one rather than find out in month four.
For everything else, control has stopped being the deciding factor. Lists, forms, maps, checkout flows, chat and feeds render smoothly in both React Native and Flutter on current hardware. Flutter made its Impeller renderer the default on iOS in 2023 to remove shader-compilation stutter. React Native made its New Architecture the default in version 0.76 in late 2024, replacing the old asynchronous bridge with direct JavaScript-to-native calls. Most of the performance complaints people still repeat were measured on versions that no longer ship.
Cost
Cross-platform wins on cost by the 15-25% worked out above for the first build. It keeps winning after launch, and that part of the case gets less attention than it deserves. With two native apps, every feature is built twice, reviewed twice and regression-tested twice, for as long as the product lives. On a product maintained for four or five years, that recurring cost of building everything twice outweighs the initial build saving. The reverse cost is the framework upgrade. Major React Native and Flutter version bumps take real engineering days, and third-party libraries that fall behind can hold up a release. Plan for one upgrade sprint a year and the numbers still come out in cross-platform's favour.
Speed
Speed is where cross-platform wins most clearly, and the reason is parity rather than raw build speed. Two native teams drift apart. A feature lands on iOS first, Android follows three sprints later, and marketing can't announce it until both are done. Otherwise it's announced anyway and half the users write in asking where it is. With one codebase, both stores get the same release in the same week. For a two-sided marketplace, where the supply side is often on Android and the demand side on iOS, that parity decides whether the marketplace works on launch day.
Risk
Risk looks even until you break it down. Cross-platform takes on a dependency risk. You rely on Meta or Google continuing to invest, and on a library ecosystem keeping up with OS releases. Meta runs React Native in its own apps, which is about as strong a commitment as open-source infrastructure gets. Native takes on a staffing risk. You need people who are strong in both Swift and Kotlin, or two separate groups, and if your one iOS engineer leaves mid-build, half your product stops. For most companies the staffing risk is the bigger one.
The risk that actually sinks cross-platform projects is bridge code. The native module that handles background location or Bluetooth pairing is where a threading bug sits for months before anyone finds it. We require every pull request to be reviewed by another senior engineer before merge, and that rule matters most here. A reviewer who only reads JavaScript will approve a Kotlin lifecycle mistake without noticing. Whoever reviews native-module code should be someone who ships Swift or Kotlin.
React Native or Flutter: Pick the Language Your Company Already Speaks
Within the cross-platform option, the React Native versus Flutter argument is usually conducted on rendering benchmarks. Those barely matter anymore. What matters is the team that will maintain the app in its third year.
React Native is written in JavaScript and TypeScript, which gives you the largest developer pool in the industry. It also shares a mental model, and often validation logic, API clients and state patterns, with a React web front end. The largest group at EltexSoft is full-stack Laravel and React engineers, and we've seen the practical benefit many times: when the web and mobile teams use the same language, one engineer can follow a bug from the React admin panel through the API into the mobile app without handing it off. If your company already runs a React web product, React Native is the right call.
Flutter is the right call when the product needs a heavily custom, pixel-identical interface on both platforms and there's no web React team to share with. Flutter draws every pixel itself, so a branded design system looks exactly the same on a Pixel and an iPhone. It has matched or passed React Native in developer usage surveys since around 2021, so it is no longer a niche choice. The cost is Dart, a language your backend and web engineers almost certainly don't write, and that makes the mobile team a separate group to staff and keep.
There's a third option for the Airbnb situation. Kotlin Multiplatform, stable since late 2023, shares business logic across platforms while keeping native UI on each side. If you already have two healthy native apps, it lets you remove duplicated logic without a rewrite. For a new product it adds complexity you don't need.
Where Native Wins Outright
Native is the correct choice when the product is essentially the device doing something. That covers camera and image pipelines where frame timing matters, real-time audio, fitness tracking that runs all day on background location and has to respect the battery, deep Bluetooth hardware pairing, and apps built around widgets, watch complications or lock-screen surfaces. In these products the native share of the code rises past a third, and at that point the shared codebase is mainly adding a translation layer between your team and the platform.
There's one more native case people underrate: a small, polished, single-platform launch. If your users are 80% on iOS (common in US consumer subscriptions) and the plan is to validate on iOS before Android exists, one good Swift app beats a cross-platform app that no one tests properly on Android. Our mobile group is deliberately deep rather than wide, with native iOS in Swift, native Android in Kotlin, and React Native. That's so this call can follow what the product needs instead of whichever toolkit the team knows.
The Call
Look at your feature list and mark each item as server-side (it fetches, displays and submits data) or device-side (it depends on sensors, background execution or OS surfaces). If more than two-thirds are server-side, which covers nearly every marketplace, booking app, SaaS companion, EdTech product and internal tool, build cross-platform. Use React Native if you have a React web team and Flutter if you don't. Budget 15-25% savings, not 50%, and set aside a senior native reviewer for the bridge code. If device-side items make up more than a third, or the roadmap includes widgets, watch apps or all-day background work, build native and accept the cost of doing the work twice, because in that case the native code is the product.
That server-or-device split is the first thing we map in a free discovery week: every feature marked, the native-module list written down, and the framework recommendation backed by the estimate rather than a preference. From there, a paid pilot with no lock-in builds the riskiest native-facing feature first, so you find out in weeks whether the bridge holds, before committing to 2-week sprints on the full build. The concrete next step is to send us your feature list, and we'll send back the split and the recommendation it supports.
Last updated November 12, 2026