When the native or cross-platform question reaches the table, it usually arrives as "which one is better?" The version of it that saves money is different: which layer of your app has to be written twice? The gap between the two paths does not show up in the quality your users experience. It shows up in how much of the work doubles between iOS and Android, and in how many places you end up writing native code no matter which framework you picked.

There is also a reason to ask the question again this year. Most of what you will read about native versus cross-platform was written before some real changes landed in the two big frameworks, and before a third path became stable enough to belong in the comparison at all. This guide works from published vendor documentation as of 22 September 2026, with dates attached.

What actually changed over the past two years

React Native: the old architecture is frozen, not merely discouraged

The most consequential change on the cross-platform side over two years is a decision to stop. The React Native release working group announced on 29 May 2025 that the legacy architecture would be frozen from 2 June 2025: no new feature work, no pull requests that touch it, no testing of it when a release ships. The only carve-outs are security fixes and bugs that make the legacy architecture unusable outright.

The new architecture had already become the default in 0.76 back in October 2024. As of 22 September 2026, the latest stable release is 0.87.1, with 0.88 still a release candidate.

If you own an app written before 2024 that still runs on the legacy architecture, the implication is concrete: you are sitting on code that is not tested at release time and does not receive fixes. That belongs in a maintenance budget line, not in an engineering footnote.

Flutter: a known release rhythm and an engine that draws everything itself

The current Flutter release is 3.47, shipped on 12 August 2026. Its approach differs from React Native's in a fundamental way. Instead of calling the system's own buttons and menus, it paints the entire interface onto a blank canvas through its own engine, Impeller, which precompiles shaders rather than compiling them at runtime, and is the only supported renderer on iOS.

Drawing everything yourself is an advantage and a constraint at once. The advantage is visual parity across both platforms with no extra effort. The constraint is that Flutter's own documentation states that while the framework ships the means to produce each platform's conventions, it does not adapt automatically when a design decision is required. In other words, "feeling native" is work you pay for, not something the framework hands you.

The third path: sharing the logic only

The third change reframes the question entirely. The Kotlin Multiplatform page on the Android developer site states that Google officially supports KMP for sharing business logic between Android and iOS, and that the platform is stable and production-ready. JetBrains' published stability table puts Android, iOS, desktop and server-side at Stable, and leaves watchOS, tvOS and web at Beta.

The interface is a separate choice. You can share only the logic and write the screens twice in SwiftUI and Jetpack Compose, or share the interface too through Compose Multiplatform, which became stable and production-ready on iOS with release 1.8.0 in May 2025 and has since reached version 1.12.0, supporting Android 5.0 and iOS 14 upward.

What makes this path practically different is that it does not demand one irreversible decision. You can start by sharing the data layer, input validation and pricing rules while keeping every screen native, then widen the shared portion later if the product proves itself. Google lists Jetpack libraries ready for exactly this, including Room, DataStore, Lifecycle, ViewModel and Paging.

Two numbers deserve a caveat. In the same stability announcement, JetBrains says Compose Multiplatform adds roughly 9 MB to an iOS app compared with a fully native SwiftUI build carrying the same UI logic and assets, and cites the Respawn app as sharing 96% of its code across platforms. Both figures come from the vendor, measured by the vendor. Read them accordingly.

The three paths side by side

Fully nativeFully cross-platformShared logic, native UI
ToolingSwift/SwiftUI and Kotlin/Jetpack ComposeFlutter or React NativeKotlin Multiplatform, with native UI or Compose Multiplatform
Written onceNothing on the client sideInterface and logic togetherBusiness logic, data, validation
Written twiceEverything on the client sideWhatever needs uncovered system APIsEvery screen, if you keep the UI native
Worth it whenHardware, sustained background work, performance sensitivityCommerce, bookings, services, tracking dashboardsLong-lived apps with heavy business rules and deliberately different interfaces
Main riskDouble the cost and two teams with two skill setsAn unmaintained wrapper package disabling a featureA newer stack, and scarcer local hiring

A decision table by app type

The technical reason in the right-hand column matters more than the recommendation itself.

App typeBetter pathTechnical reason
Online store or catalogueCross-platformThe work is network calls, lists, forms and a payment gateway; none of it needs an uncovered system API
Appointment or service bookingCross-platformNotifications, calendar and maps all have mature, maintained packages in both frameworks
Delivery with courier trackingCross-platform for the customer app; price the courier app separatelyBackground location on Android 11 and up is not granted from the system dialog but from the Settings page, and tuning background behaviour on both platforms is native work either way
Bank or walletNative, or shared logic with native UIDepends on the keystore, biometric authentication and tamper detection, all system APIs that shift with each OS release
Internal staff toolCross-platformFew users, known devices, speed over polish; and often a website serves you better than an app
Game or heavy graphicsA game engine, neither of the aboveUnity or Unreal is the natural path; comparing Flutter with Swift here misses the point
Health and fitnessNative, or shared with native modulesHealth Connect is Android-only from SDK 28 upward, and its iOS counterpart is entirely separate, so the health layer gets written twice regardless
Augmented realityNativeOnly some ARCore APIs are available on both platforms, and Apple's guideline 4.2.1 demands a rich, integrated AR experience rather than a model dropped into a view

What actually breaks cross-platform

The familiar claim that cross-platform "cannot reach the full device" is imprecise, and the precise version is harder: it can reach it, through native code that you write inside the unified project.

Flutter's platform channel documentation says so plainly: platform-specific code is written in that platform's own language, meaning Kotlin or Java on Android and Swift or Objective-C on iOS, exchanging messages with Dart across a channel. The same principle governs React Native's native modules.

So the question worth putting to your developer is this: does a maintained package already cover this case, or will I pay to write and maintain it twice? These are the cases where the answer lands on the expensive side.

With the camera, ordinary capture and code scanning have mature packages, while manual exposure and focus control, real-time frame processing or rapid burst capture all fall back to each system's camera APIs.

Bluetooth Low Energy (BLE) is covered as long as the app is in the foreground; connecting and reading work through an off-the-shelf package. Background operation and reconnecting after the app closes need configuration and native code on each platform, and the two systems behave differently to begin with.

Sustained background work is a separate case: continuous location tracking, scheduled sync, jobs that must not stop. The constraints come from the operating system rather than the framework, and each system has its own permissions and its own behaviour when the app is closed.

On in-app payments, Apple's guideline 3.1.1 requires in-app purchase to unlock features or content inside the app, while 3.1.3(e) forbids it for goods and services consumed outside the app. Packages cover the purchase itself, but receipt validation and subscription state on your server remain two separate systems.

Planning to build or scale a digital project?

Snaabble provides a tailored technical assessment to define the right stack & exact budget.

For health, fitness and augmented reality, the two platform stacks are independent, with different data types, permissions and review expectations, and no AR experience clears Apple review without native work.

The local case: integrating with an authority that publishes no documentation

Add a case that matters to anyone building for this region: integrating with an authority that publishes no developer documentation. Where there is no published guide and no announced sandbox, no maintained package exists in Flutter, React Native or KMP, and no one has a reason to build one.

A live example is identity verification through Nafath in Saudi Arabia, where there is no published developer guide, no announced test environment and no official protocol description; the documents arrive after you contract with the operator. In practice this means writing a native integration layer on both platforms against a specification you have not yet seen. If that integration is in your scope, budget hours for it as native work regardless of the path you choose.

Where the cost difference actually sits

The line that cross-platform "saves half the cost" puts the half in the wrong place. The saving falls on the client side alone, not on the budget as a whole.

Split the project into three groups.

One group never doubles on any path: server, database and API, admin dashboard, design and user research, requirements analysis and scoping, setting up both store accounts and listings, and project management. These lines take a large share of the hours in any business app, and they are identical across paths, so no price difference between two quotes originates here.

Another doubles fully on the native path alone: building screens and wiring them to the API, state management and navigation, and testing on both platforms.

And a third stays native in every scenario: every item from the previous section, plus notification and permission handling per platform.

So the saving equals roughly half the client-side share, minus whatever stays native. That is why the gap widens on a simple retail app and narrows on a courier app that runs in the background, even though a quote calls both of them "a mobile app".

A worked example

Hypothetical example for a mid-sized retail app, with range estimates rather than prices: assume 700 hours for server, API, dashboard, design and management; 600 hours for the client side on one platform; and 120 hours of residual native work on the cross-platform path.

NativeCross-platform
Does not double700700
Client side1,200600
Residual native worknone120
Total1,900 hours1,420 hours

In this example the difference is roughly a quarter of the project, not half of it. Multiply the 480-hour gap by the hourly rate stated in your own quote, in pounds or riyals, and you get the figure that applies to you. We will not invent an hourly rate for you: no official benchmark is published for Egypt or Saudi Arabia, and the practical method is to collect three itemised quotes, as set out in our breakdown of mobile app cost lines in Saudi riyals.

Store fees do not distinguish the two paths

A frequent source of confusion: the Apple Developer Program at 99 USD per membership year, the one-time 25 USD Google Play registration fee, and store commissions on digital content are identical on both paths. If two quotes differ on these lines, they differ in presentation rather than in cost. These fees are broken down in our PWA versus native app cost comparison.

Annual maintenance: the difference shows up in year two

In year one the numbers clearly favour the cross-platform path. In year two another factor enters: how many ecosystems you have to track.

Going native means tracking two annual releases, Apple's and Google's. Going cross-platform means tracking three: those same two, plus the framework's own cadence and the wrapper-package upgrades it forces. That third one is not small. The published React Native support policy confines active support to a narrow band of the newest releases, and requires Xcode 26 as a minimum for 0.87 and 0.88, along with JDK 17 and Node 22.11.

What that means to an owner rather than an engineer: requiring a specific Xcode version means a Mac that supports it and a refreshed CI build image. That line appears in year two, not in the first quote. Put it in the budget now, and see our guide to mobile app development timelines for where upgrade windows land in a schedule.

Stated plainly: cross-platform is cheaper to maintain when you have a regular update plan, and more expensive when the app is built once and left for two years, because you then pay an accumulated upgrade in a single bill.

Start cross-platform and switch later: what does the switch cost?

This is a legitimate route, and often the right call when you are testing an idea. Just describe the switch precisely before you rely on it: what carries over and what gets rebuilt.

Carries over unchanged: the server, API and database, the admin dashboard, the design system and assets, both store accounts with their listings and user ratings, and everything you learned about how people actually use the product.

Gets rebuilt: the entire client side, twice.

Put differently, the switch costs you roughly what the native path would have cost for the client side from the start, after you have already paid once for the first path. The arithmetic favours you when the first app has confirmed or killed the demand. It works against you when you knew from day one that the app depends on hardware or background execution.

Three decisions lower that bill, and all three are made before the first line of code:

  1. Separate the API from the user interface at the outset. If the business logic lives on the server, the switch only touches the screens.
  2. Isolate everything native in standalone modules. A payment, Bluetooth or local-integration layer written as a separate module moves into the native project with modest effort.
  3. If you already expect to switch, consider the third path instead of the first, because sharing business logic behind a native UI turns "switching" into gradual expansion rather than a rewrite: the screens are native from day one and the logic stays shared.

How to read the two quotes in front of you

If you are comparing quotes right now, three questions expose the difference faster than any table.

Ask for an hours table broken down into server, client side, native work and management; a quote that gives one number cannot be compared with anything. Ask for the list of wrapper packages the app will depend on and who maintains them, because an abandoned package disables an entire feature at the first OS update. Finally, ask about the annual upgrade line: who raises the framework version, for how much, and when.

And if you have settled on the cross-platform path, choosing between Flutter and React Native is a separate question with its own criteria: release cadence, tooling requirements, and what your team already knows. We covered it in Flutter versus React Native, compared by releases and numbers. If you are at an earlier stage, start from the store-rule decisions that come before any code.

That breakdown is what the discovery session at Snaabble is for: defining the scope before any code is written, because recommending a path before you know what falls on each side is guesswork. Walk the team through your app requirements and you will get a reasoned path recommendation and an initial estimate of duration and cost within a day. No charge, and nothing follows from it.

Sources