Kotlin Multiplatform and Compose Multiplatform: Multi-Native Mobile in 2026
On this page (19sections)
React Native and Flutter walked so Kotlin Multiplatform could run. That line is a hot take — but after spending real project time in Kotlin Multiplatform (KMP) and Compose Multiplatform (CMP), I do not expect to go back to traditional hybrid stacks for the kind of products I build.
This is not a marketing slide. It is the honest engineer-to-engineer breakdown I wish I had when evaluating our 2026 mobile stack: what KMP actually is, how the architecture works, who ships it in production, where Compose on iOS still needs care, and how it compares to React Native and Flutter on numbers that matter.
The short version
KMP is not “another hybrid framework.” It is a different philosophy:
- You do not ship a runtime — you compile to true native binaries.
- You do not fake native — you share logic, then use real SwiftUI, UIKit, or Compose for UI.
- You do not choose 80% native OR 100% shared — you choose per screen, per module, per team.
If you already write Jetpack Compose on Android, you are most of the way there. One Kotlin codebase can target Android, iOS, Web, and Desktop — with platform-specific UI only where you decide you need it.
The future of cross-platform mobile is not hybrid. It is multi-native.
Hybrid vs multi-native: what actually ships in your APK/IPA
Traditional hybrid stacks bundle an interpreter or bridge:
| Approach | What runs on device | UI rendering | Typical shared surface |
|---|---|---|---|
| React Native | JavaScript + native modules via bridge | Native components driven from JS | JS/TS logic + React components |
| Flutter | Dart VM + Skia engine | Skia-drawn widgets (not native controls) | Dart UI + logic (~100%) |
| Kotlin Multiplatform | Compiled Kotlin → platform code | Native (Compose, SwiftUI, UIKit) | Kotlin logic; UI optional per target |
| Compose Multiplatform | Compiled Kotlin | Compose runtime on each platform | Kotlin UI + logic when you opt in |
Bridge cost (React Native): Meta’s own architecture docs describe the async JavaScript-to-native bridge as a serialization bottleneck. New Architecture (JSI, Fabric, TurboModules) reduces but does not eliminate that boundary. For animation-heavy or chat-style UIs, bridge chatter still shows up in profiles.
Engine cost (Flutter): You ship Skia and the Dart runtime. App size and memory footprints are predictable but not zero — Flutter’s FAQ notes minimum overhead compared to a minimal native app. You gain pixel consistency; you trade away native control widgets on every screen.
KMP cost: Shared Kotlin compiles to JVM bytecode on Android, native ARM/x64 on iOS (via Kotlin/Native), and analogous targets elsewhere. No JS bridge. No Dart VM in your process unless you add one yourself.
Architecture: how a production KMP app is layered
Most successful teams do not start with 100% shared UI. They start with a shared core and native (or Compose) shells.
┌─────────────────────────────────────────────────────────────────┐
│ Presentation (per platform) │
│ Android: Jetpack Compose iOS: SwiftUI / UIKit / CMP │
│ Desktop: Compose Desktop Web: Compose for Web (optional) │
└───────────────────────────────┬─────────────────────────────────┘
│ ViewModels, UI state (often shared)
┌───────────────────────────────▼─────────────────────────────────┐
│ Shared feature modules (KMP) │
│ Use cases · Repositories · Domain models · Validators │
└───────────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────────▼─────────────────────────────────┐
│ Shared infrastructure (KMP) │
│ HTTP client (Ktor) · Serialization (kotlinx.serialization) │
│ Coroutines · Settings · Analytics event builders │
└───────────────────────────────┬─────────────────────────────────┘
│ expect/actual or interfaces
┌───────────────────────────────▼─────────────────────────────────┐
│ Platform adapters │
│ Android: Room, WorkManager iOS: Core Data, BGTaskScheduler │
│ Secure storage, push tokens, billing SDK wrappers │
└─────────────────────────────────────────────────────────────────┘
Module map (Gradle)
A Gradle structure that scales to multiple features without turning into a ball of mud:
my-app/
├── shared/
│ ├── core/ # logging, dispatchers, result types
│ ├── network/ # Ktor, API models
│ ├── domain/ # use cases, pure Kotlin
│ └── feature-login/ # login repository + ViewModel
├── androidApp/ # Compose Activity, Hilt, Room
├── iosApp/ # Xcode project, SwiftUI shell
└── desktopApp/ # optional Compose Desktop entry
expect/actual (or interface + platform implementations) is the escape hatch. Shared code declares expect fun openUrl(url: String); Android and iOS provide actual implementations. That is how you keep Keychain and EncryptedSharedPreferences behind one Kotlin interface.
Data flow (MVVM-friendly)
This aligns with Clean Architecture on Android — the same layers, exported into commonMain:
- UI collects user events (Compose, SwiftUI, or both).
- ViewModel (often in
commonMain) exposesStateFlowUI state. - Use case orchestrates domain rules — pure Kotlin, easy to unit test on JVM.
- Repository merges remote and local sources.
- Platform adapters implement storage, permissions, and SDK calls.
If you already use MVVM on Android, see our Android MVVM guide — the mental model transfers directly; the ViewModel simply moves up one Gradle module.
The numbers: adoption, ecosystem, and momentum
These are the figures I use when talking to platform leads — all linked to primary sources so you can verify before a roadmap meeting.
| Metric | Figure | Source |
|---|---|---|
| Kotlin on Android | ~93% of top 1,000 Google Play apps use Kotlin (2024) | Android Developers Blog — State of Kotlin on Android |
| KMP project growth | 2×+ year-over-year increase in KMP projects indexed by JetBrains (2023 survey) | Kotlin Multiplatform in 2023 — JetBrains |
| Compose Multiplatform targets | Android, iOS, Desktop, Web from one Compose UI codebase | Compose Multiplatform — JetBrains |
| Official stability | KMP Stable as of Kotlin 1.9.20 (Nov 2023) | Kotlin 1.9.20 release |
| Google + JetBrains alignment | Android Jetpack libraries migrating to KMP-compatible artifacts | AndroidX multiplatform announcements |
Who ships KMP in production?
JetBrains maintains a public case studies page — these are not slide-deck logos; they are teams that published engineering write-ups:
| Company | What they share | Notes |
|---|---|---|
| Netflix | Product reliability tooling | Production Focused Kotlin Multiplatform — Netflix TechBlog |
| McDonald’s | Mobile SDK and shared logic across markets | Referenced in KotlinConf case studies |
| Cash App (Block) | Shared business logic between Android and iOS | Square/Block engineering talks on KMP for payments flows |
| Forbes | Content and authentication layers | Kotlin Multiplatform adoption for reader apps |
| Philips, VMware, 9GAG | Various shared cores | Listed with technical detail on kotlinlang.org |
Takeaway: KMP is past the “only startups experiment” phase. Large consumer and enterprise apps share networking, models, and feature logic today. UI strategy varies — some teams are Compose-heavy; others keep SwiftUI and use KMP strictly below the presentation layer.
Why teams quietly switch
1. True native performance
Shared Kotlin on iOS compiles to native machine code through Kotlin/Native. Hot paths do not cross a JavaScript bridge. Compose Multiplatform on iOS uses Skia (similar rendering model to Flutter for Compose-drawn pixels) — but you can render only the screens you choose with Compose and keep the rest in SwiftUI.
2. Granular control
You are not locked into a single UI paradigm:
- Share everything except the iOS settings screen.
- Share ViewModels but not composables.
- Share nothing UI-related for release 1 — only domain + data — and add CMP in release 2.
That per-screen knob is hard to replicate in RN or Flutter without platform channels or federated plugins.
3. Jetpack Compose skills transfer
Google invests in Compose on Android; JetBrains invests in Compose Multiplatform. The @Composable mental model, state hoisting, and Navigation Compose patterns you learn for Android apply on iOS and Desktop with documented deltas. If your team already standardized on Compose, CMP lowers the second-platform cost compared to learning SwiftUI from zero — though Apple HIG still matters for polish.
4. Ecosystem fit for backend-heavy teams
Kotlin is the same language many teams use on Ktor, Spring, and Gradle. Sharing DTOs, validation, and client SDKs between mobile and server (via Kotlin Multiplatform libraries) is underrated — fewer “the API changed and three repos drifted” incidents.
Compose Multiplatform on iOS: production-ready or not yet?
Honest answer: it depends on your risk tolerance and UI complexity.
Ready enough for many teams:
- Standard form flows, lists, settings, auth wizards
- Apps already theming Compose on Android and wanting visual parity
- Internal tools and B2B apps where App Store pixel perfection is secondary
Still exercise caution:
- Heavy platform integrations (Live Activities, complex maps, ARKit)
- Highly custom transitions matching iOS system feel
- Large legacy UIKit codebases where incremental SwiftUI migration is already underway
JetBrains marks Compose Multiplatform for iOS as a major focus with regular releases; check the release notes before you freeze versions. My rule: prototype the three hardest screens in week one. If scrolling, keyboard inset, and accessibility are acceptable, proceed. If not, default to shared ViewModels + SwiftUI.
For App Store packaging, distribution, and review pitfalls, pair this guide with Apple distribution strategies and the iOS submission prerequisites checklist.
Comparison scorecard (2026 evaluation)
Subjective but grounded in field experience — use it as a discussion starter, not a verdict.
| Criterion | React Native | Flutter | KMP + CMP |
|---|---|---|---|
| Time-to-first-screen (greenfield) | Fast | Fastest uniform UI | Moderate (Gradle + Xcode setup) |
| Peak native performance | Good with New Architecture | Very good; Skia everywhere | Excellent when UI is native; very good with CMP |
| Hiring pool | Largest JS/React pool | Strong Dart/Flutter pool | Strong Android/Kotlin pool; iOS still needed |
| UI fidelity to platform HIG | Good with platform components | Consistent but “non-native” feel | Excellent when using SwiftUI/UIKit |
| Shared UI percentage | High | ~100% | Your choice (0–100%) |
| App size overhead | Moderate (Hermes + bundles) | Moderate (engine) | Lower for logic-only sharing |
| Web + desktop bonus | React Native Web (extra stack) | Flutter Web/Desktop | Compose Multiplatform Desktop/Web |
A practical adoption path (90 days)
Days 1–14 — Spike
- Create
sharedmodule with one API call (Ktor) and one repository. - Wire Android Compose screen to shared ViewModel.
- Expose same ViewModel to a minimal SwiftUI screen on iOS.
- Measure: build times, iOS binary size delta, developer ergonomics.
Days 15–45 — First feature module
- Migrate one bounded feature (e.g. login or profile) to shared domain + data.
- Keep UI native on iOS if CMP feels risky; use Compose on Android.
- Add unit tests in
commonTest— this is where KMP pays off fastest.
Days 46–90 — Platform hardening
- expect/actual for secure storage, analytics, feature flags.
- CI:
:shared:check, Android instrumented tests, iOSxcodebuildon simulator. - Document which screens are shared UI vs native in your developer checkpoints list.
What I would tell Flutter and React Native devs
If you are on React Native: You likely stay because of JavaScript talent density, Expo velocity, and Meta’s ecosystem. Fair. KMP becomes interesting when bridge jank, native module maintenance, or type safety across the stack hurts — not because Kotlin is fashionable.
If you are on Flutter: You likely stay because one UI codebase genuinely works for your product shape. KMP + CMP competes most directly here — both target “write once, adjust per platform.” The difference is who owns the pixels: Flutter always Skia; CMP mixes Compose-rendered and truly native screens in one app.
If you are Android-first: You have the shortest path. Your existing Jetpack architecture, Gradle fluency, and Compose skills are the onboarding.
Tooling and official links
- Kotlin Multiplatform documentation
- Compose Multiplatform getting started
- Android Kotlin Multiplatform guide
- KMP case studies and adoption stories
- Kotlin Multiplatform samples (GitHub)
Closing take
Evaluating your 2026 mobile tech stack is not about picking the winner on Twitter. It is about where you want shared code to live, how much native feel you owe your users, and what your team already knows.
Kotlin Multiplatform did not replace React Native or Flutter overnight. It gave Android-heavy and Kotlin-native teams a credible way to share real logic — and, when ready, real Compose UI — without shipping someone else’s runtime in every build.
The question is not “hybrid or native.” It is how multi-native you want to be, screen by screen.
Originally sparked by a LinkedIn discussion on KMP vs hybrid stacks — expanded here with architecture diagrams, sources, and links for a full technical read.
Frequently Asked Questions
Is Kotlin Multiplatform just another hybrid framework like React Native?
Is Compose Multiplatform production-ready for iOS?
Should we migrate from Flutter or React Native to KMP?
What can we realistically share with KMP?
Related Tutorials
Mastering Android Jetpack: Clean Architecture
Layered architecture patterns that map cleanly onto a KMP shared core.
Read tutorialBuilding Flexible Android Apps with MVVM
ViewModel and repository patterns you can lift into shared Kotlin modules.
Read tutorialApple Distribution Strategies for iOS Apps
Store distribution paths when you ship a KMP app with a native or Compose iOS shell.
Read tutorial