Kotlin Multiplatform vs Flutter: share the logic, keep the interface native
Kotlin Multiplatform can share business rules while keeping interfaces native. Assess fit against your app's complexity and your team's Kotlin and UI skills.
Most comparisons of Kotlin Multiplatform, Flutter and React Native are feature tables. The more useful question is which code should be shared at all. For products on both iPhone and Android with substantial client-side rules and a team able to own Kotlin and both native interfaces, I recommend sharing the business logic: pricing rules, validation, data models, sync and offline behaviour. The interface is better left native. Duplicated logic produces bugs that cost money and are hard to see. A shared interface produces shortcuts that each platform's users notice. Google's May 2024 backing strengthens the case for that split. It does not remove the staffing, build and interoperability costs each team must assess.
What Google actually backed
At Google I/O on 14 May 2024, the Android team announced official support for Kotlin Multiplatform (KMP). The wording is narrower than the headlines that followed. Google said its focus was "sharing business logic (the parts that are most agnostic to the user interfaces)", because that is where it had seen Android developers "get the most value in not having to maintain duplicate copies of this code."
The announcement came with evidence that was more than a press line. The Google Docs app for Android, iOS and the web used KMP for its shared business logic, and the Workspace team described KMP as the direction for its multi-platform architecture. Several Jetpack libraries gained KMP support: Annotations, Collections and DataStore in stable versions, with Room, Lifecycle and ViewModels in alpha. The Android Gradle Plugin gained official support for KMP targets, and Android engineers reported an 18% runtime improvement in Kotlin/Native compiler benchmarks.
The technology itself was not new. JetBrains had declared Kotlin Multiplatform stable in Kotlin 1.9.20 in November 2023. At that point Compose Multiplatform, the option for sharing the interface too, was still alpha on iOS. What changed in May 2024 was the risk profile. A team choosing KMP was no longer betting on one tool vendor alone. The owner of Android had put its own flagship app and its own libraries behind the approach, and it had chosen to put them behind the logic layer specifically.
Where duplicated logic costs money
Consider what two native apps without shared code actually duplicate. Every rule about money, eligibility, dates and state is written once in Kotlin and once in Swift, by different people, usually at different times. A small example of the kind of code that belongs in a shared module:
This is a rounding-only illustration, not a complete pricing function. Assume inputs have already been validated: prices and quantities are nonnegative, each multiplication and the sum fit in Long, and gross * discountPercent also fits in Long. The sample validates only the discount range. Production code needs those bounds enforced before calling it.
// commonMain: compiled for Android and for iOS
data class OrderLine(val unitPriceCents: Long, val quantity: Int)
fun orderTotalCents(lines: List<OrderLine>, discountPercent: Int): Long {
require(discountPercent in 0..100) { "Discount must be between 0 and 100" }
val gross = lines.sumOf { it.unitPriceCents * it.quantity }
return gross - gross * discountPercent / 100
}
The integer division at the end discards the remainder, so the discount is rounded down and the customer pays the extra fraction of a cent. That is a business decision. Written twice, it gets made twice, and nothing guarantees the Swift version makes it the same way. Multiply that by discount stacking, tax, time zones, retry rules for an offline queue and conflict resolution when two devices edit the same record. These divergences do not crash. They show up as a support ticket saying the iPhone app charged a different amount, or as a sync bug that only appears when an Android and an iOS user share an account. They are expensive because they are found late, by customers.
A shared module gives that logic one implementation and one test suite. That is the strongest argument for KMP, and it is an argument about risk more than speed.
Where a shared interface costs you on iOS
The interface is the opposite case. Platform differences there are not bugs to eliminate. They are what users expect: navigation gestures, text selection, system sheets, accessibility behaviour and, increasingly, the look of the system itself.
The clearest test came after the period this article looks back on. In June 2025 Apple introduced Liquid Glass, a new design material across iOS 26 and its other systems, which Apple called its "broadest software design update ever." For apps built with SwiftUI and UIKit, Apple shipped updated APIs and controls to adopt the new design. Flutter takes a different approach: according to its architectural overview, it "has its own implementations of each UI control, rather than deferring to those provided by the system." The day after Apple's announcement, the Flutter team stated in the issue tracking Liquid Glass support that it was "not developing the new Apple'26 UI design features in the Cupertino library right now." In July 2025 it added that the Cupertino library was being moved into a separate package where that work would happen. The issue was still open in November 2026.
That is not a criticism of Flutter's engineering. Drawing every control yourself is a deliberate trade, and it buys consistency across platforms and control over rendering. The cost is that when the platform changes, your app waits for the framework. React Native sits in between: its documentation says it creates "the corresponding Android and iOS views" at runtime, so it is less exposed to this particular problem. A KMP app with a SwiftUI interface is in the same position as any native app, because the interface is Apple's.
What changed in two years
Two years on, the picture has moved in both directions.
The case for sharing more has grown. JetBrains declared Compose Multiplatform for iOS stable in May 2025, with version 1.8.0. KMP is no longer only a logic layer: the release notes describe embedding Compose in an existing iOS app and placing native views inside a Compose screen, so a team can share some screens and keep others native. That flexibility is useful. It also brings back the 2024 question in a new form. The same release notes list scrolling that "matches native iOS physics" and native text selection as details JetBrains had to get right, which is the kind of catch-up work any shared interface carries on iOS.
The iOS side of KMP has also remained its weak point. Kotlin/Native, according to the Kotlin documentation, "provides indirect interoperability with Swift through Objective-C." Suspending functions arrive in Swift as completion handlers or async functions, and Google's 2024 announcement itself pointed to Touchlab's SKIE to make modern types and coroutines usable from Swift. The direct path, Swift export, is still described as Alpha. In practice an iOS developer on a KMP team works against a generated API they did not design. That is a real cost, and it falls on the platform where users are the most demanding about polish.
The strongest case against
The best argument against the split is cost. Keeping the interface native means two interface codebases, two sets of interface skills and two rounds of interface testing. For a small team with one designer, building an internal app for staff, that is hard to justify. Staff use the app because their job requires it, not because it feels like iOS. A single Flutter or React Native codebase gets them a working app on both platforms with one team, and if the interface lags a platform redesign by a year, nobody leaves.
That is a sound decision, and the conclusion here does not cover it. It also does not hold in three other situations:
- The app is iOS only, or Android only. There is nothing to share between platforms, and KMP adds a build layer for no benefit. Many products should start on one platform, which is a separate decision covered in web app vs mobile app.
- The rules live on the server. If prices, permissions and validation are decided by your backend and the apps only display results, the duplication problem is small. Moving logic to the server is often a better answer than sharing it on the client.
- The team has no Kotlin experience. An iOS team adopting KMP takes on Gradle, a second language and a second debugger. Without someone who owns the shared module, it becomes the part nobody wants to touch.
The position
For a customer-facing product on both platforms, with rules that matter to the business, share the logic and keep the interface native. Google's May 2024 announcement did not make KMP perfect. It supplied platform-owner backing and a production example at scale. For the team and product constraints above, that supports my recommendation; it does not establish low project risk. The interface is where your users judge the product, and the platforms keep changing it.
Our iOS app development service covers iPhone and iPad products. Reuse on a later Android app is a project-specific architecture decision: it depends on where the rules live, the team’s skills and the agreed scope. Starting on iPhone alone does not require a shared Kotlin module.
Sources
- Android Support for Kotlin Multiplatform (KMP) to Share Business Logic Across Mobile, Web, Server, and Desktop, Android Developers Blog, 14 May 2024
- Google I/O 2024: Kotlin Multiplatform at Google Scale!, Touchlab, 14 May 2024
- Kotlin Multiplatform Is Stable and Production-Ready, JetBrains, 1 November 2023
- Compose Multiplatform 1.8.0 Released: Compose Multiplatform for iOS Is Stable and Production-Ready, JetBrains, 6 May 2025
- Apple introduces a delightful and elegant new software design, Apple Newsroom, 9 June 2025
- Support for iOS 26 "Liquid Glass" Design in Cupertino Widgets, flutter/flutter issue 170310, opened 10 June 2025
- Flutter architectural overview and Core Components and Native Components, Flutter and React Native documentation, read November 2026
- Interoperability with Swift/Objective-C and Interoperability with Swift using Swift export, Kotlin documentation, read November 2026
Paul