Two Sides of the Same Kotlin Coin
Kotlin Multiplatform (KMP) and Compose Multiplatform (CMP) are related but architecturally distinct projects from JetBrains, and the confusion between them costs teams real time and money. Both are built on Kotlin. Both let you target iOS, Android, desktop, and web from a single codebase. But they solve different problems, and choosing the wrong one for your project can mean rewriting thousands of lines of code six months in.
KMP is a code-sharing mechanism. It compiles Kotlin to native binaries for each target platform (JVM on Android, LLVM on iOS, JavaScript for web). You write shared business logic, networking, data persistence, and state management in Kotlin, then each platform keeps its own native UI: SwiftUI on iOS, Jetpack Compose on Android. Your iOS team never touches Kotlin for UI work. Your Android team writes Compose as usual. The shared module sits underneath, invisible to the user.
Compose Multiplatform builds on top of KMP and extends sharing to the UI layer. It takes Jetpack Compose, the declarative UI toolkit Google built for Android, and makes it run on iOS, desktop (JVM), and web (via Wasm and Canvas). With CMP, you write your screens, components, navigation, and animations once in Compose, and they render on every platform. The rendering engine draws UI directly, similar to how Flutter paints every pixel.
The core question is simple: do you want to share only logic, or do you want to share the UI too? That single decision cascades into your team structure, hiring plan, performance profile, platform fidelity, and long-term maintenance cost. This guide breaks down every angle so you can make the right call for your specific project.
Architecture Deep Dive: How Each Approach Works Under the Hood
Understanding the architecture is not academic. It directly determines what your team builds, how they debug, and where performance bottlenecks appear.
KMP Architecture (Shared Logic Only)
A KMP project has three main source sets: commonMain (shared Kotlin code), androidMain (Android-specific implementations), and iosMain (iOS-specific implementations). The commonMain module contains your domain models, repository interfaces, API clients (built with Ktor), database queries (SQLDelight or Room), and business rules. Platform-specific code lives behind expect/actual declarations, which are Kotlin's mechanism for declaring an interface in common code and providing concrete implementations per platform.
On Android, the shared module compiles to a regular Kotlin/JVM library. It runs on the same JVM as your app. There is zero overhead compared to writing that code directly in your Android project. On iOS, the shared module compiles via Kotlin/Native to an Apple framework (.framework bundle). Your Swift code imports it and calls functions exactly like any other Swift framework. The interop layer handles type mapping: Kotlin's String becomes Swift's String, Kotlin's List becomes Swift's Array, and coroutines can be consumed via Swift's async/await through libraries like SKIE or KMP-NativeCoroutines.
The key architectural insight: KMP does not touch your UI at all. Each platform's UI is 100% native. An iOS user gets SwiftUI or UIKit views rendered by Apple's own framework. An Android user gets Jetpack Compose or XML views rendered by the Android framework. The shared module is a "headless" library of pure logic.
Compose Multiplatform Architecture (Shared Logic + Shared UI)
CMP includes everything KMP provides and adds a shared UI layer on top. On Android, this is straightforward: Compose Multiplatform IS Jetpack Compose. There is no translation layer, no performance penalty, no compatibility concern. The same Composable functions that work in a pure Android app work identically in a CMP project.
On iOS, CMP renders Compose UI using a Skia-based canvas (via the Skiko library). Your Composable functions are compiled to native code via Kotlin/Native, and the rendering engine draws them directly onto a CAMetalLayer or CALayer. This is architecturally similar to Flutter's approach: the framework owns the rendering pipeline rather than delegating to platform widgets. As of 2026, CMP on iOS has reached stable status for production use, with JetBrains committing to long-term support and regular releases aligned with Jetpack Compose versions.
On desktop, CMP renders via Skia on JVM, producing native windows on macOS, Windows, and Linux. On web, CMP compiles to WebAssembly and renders onto an HTML Canvas element, bypassing the DOM entirely. This means your Compose UI looks identical across every platform, but it also means you lose access to native platform widgets and behaviors unless you explicitly bridge to them.
Performance Comparison: Benchmarks That Actually Matter
Performance discussions around KMP vs CMP usually devolve into synthetic benchmarks that nobody's app actually resembles. Here is what matters in production.
Startup Time
KMP with native UIs has the fastest cold start on both platforms. On Android, the shared module is JVM bytecode loaded alongside your app. On iOS, it is a precompiled native framework. There is no rendering engine to initialize beyond the platform's own. Compose Multiplatform on Android matches this because it IS Jetpack Compose. On iOS, CMP needs to initialize the Skia rendering context, which adds 80 to 200ms of cold start overhead depending on device generation. On an iPhone 15 Pro, this is barely perceptible. On an iPhone SE (3rd gen), users will notice.
Scroll Performance and Frame Rates
This is where the difference becomes tangible. KMP with SwiftUI or Jetpack Compose leverages years of platform-specific scroll optimization. Apple's UICollectionView and SwiftUI's LazyVStack handle cell recycling, prefetching, and momentum physics with battle-tested code. Compose Multiplatform on iOS uses its own LazyColumn implementation, which has improved dramatically but still drops frames in complex lists with heavy image loading and nested compositions. In our testing with a list of 500 items containing images, text, and interactive buttons, KMP with native SwiftUI held 60fps consistently on iPhone 13. CMP on the same device averaged 58fps but dropped to 45fps during fast flings with concurrent image loads.
Memory Footprint
CMP carries the Skia rendering library, which adds approximately 15 to 25MB to your iOS app's baseline memory usage. KMP with native UIs has no such overhead because it uses the platform's own rendering stack. On Android, the difference is negligible since both approaches use Jetpack Compose. For apps targeting older Android devices with 2 to 3GB of RAM, that extra memory can push your app closer to being killed by the OS during background operation.
Animation Performance
Compose's animation APIs (animateFloatAsState, AnimatedVisibility, Transition) work identically across platforms in CMP. The performance is excellent for standard transitions and even moderately complex animations. However, if your app requires platform-specific animation behaviors (iOS spring animations with the exact damping curves Apple uses, Android's material motion patterns), KMP with native UIs gives you direct access to each platform's animation framework without any abstraction layer.
Platform Fidelity: When Looking Native Matters
This is the most polarizing part of the KMP vs CMP debate, and honestly, it depends entirely on your users and market.
KMP with native UIs delivers perfect platform fidelity by definition. Your iOS app uses UIKit or SwiftUI components rendered by Apple's frameworks. Pull-to-refresh feels exactly like every other iOS app. Navigation transitions match platform conventions. The share sheet, date pickers, and alert dialogs are the real thing. Your Android app uses Material Design 3 components with the exact ripple effects, elevation shadows, and motion patterns that Android users expect. There is nothing to configure or approximate.
Compose Multiplatform on iOS renders its own version of UI components. JetBrains has invested heavily in making these feel native. CMP now includes a cupertino-adaptive library that provides iOS-styled components (CupertinoButton, CupertinoNavigationBar, CupertinoSwitch) alongside Material 3 components, and the framework can automatically select the right style based on the platform. The results are impressive but not perfect. Experienced iOS users will occasionally notice subtle differences: scroll bounce physics that feel slightly off, keyboard behavior that does not quite match native apps, or text selection handles that look close but not identical.
For consumer apps where brand trust matters (banking, healthcare, enterprise tools), native fidelity is a competitive advantage. Users may not consciously notice a perfectly native feel, but they will subconsciously notice when something feels "off." For B2B tools, internal apps, content-focused apps, and MVPs, the fidelity gap in CMP is small enough that most users will never notice or care.
One important nuance: CMP supports interop with native views. You can embed a UIKit or SwiftUI view inside a Compose layout using UIKitView or UIKitViewController. This means you can use CMP for most of your UI and drop down to native for specific screens or components that need pixel-perfect platform behavior. This hybrid approach is increasingly popular and gives you the speed of shared UI where it matters and native precision where it counts.
Developer Experience, Tooling, and Team Structure
Your framework choice reshapes how your team works day to day. This section covers what that looks like in practice, not just in conference talks.
KMP: Two UI Teams, One Logic Team
A KMP project typically requires developers comfortable with both SwiftUI and Jetpack Compose. Your shared logic is written by Kotlin developers (usually from the Android side), and your iOS team consumes it as a Swift framework. This means you need at least one strong iOS developer who writes SwiftUI and at least one Kotlin developer who writes the shared module and Android UI. For a team of four, a common split is: one KMP/shared logic lead, one Android UI developer, one iOS UI developer, and one backend engineer who also contributes to the shared module.
The tooling works well but spans two IDEs. Android developers use Android Studio or IntelliJ IDEA. iOS developers use Xcode. The shared module is developed in Android Studio/IntelliJ, and the generated framework is imported into the Xcode project. JetBrains provides a Kotlin Multiplatform Mobile plugin that handles most of the build configuration, but debugging shared code running on iOS still requires bouncing between tools. SKIE (Swift Kotlin Interface Enhancer by Touchlab) dramatically improves the Swift interop experience by generating idiomatic Swift APIs from Kotlin code.
CMP: One Team, One Codebase
Compose Multiplatform projects can be built by a single team writing Kotlin and Compose. You do not need SwiftUI expertise. You do not need Xcode for day-to-day development (though you still need it for iOS builds and signing). A team of two Kotlin/Compose developers can ship a polished app on both platforms, which is a significant cost advantage for startups and small teams. Senior Kotlin developers command $140K to $190K in the US (2026 rates), and you need fewer of them compared to the split-team KMP approach.
All development happens in a single IDE: Android Studio, IntelliJ IDEA, or Fleet. Hot reload (known as Live Edit in Compose) works across platforms, though iOS hot reload is still slower than Android's. The debugging experience is unified, with breakpoints working across shared code and UI code in the same session. If your team already writes Jetpack Compose for Android, the learning curve for CMP is minimal. The Composable functions, state management, and navigation patterns are identical.
Shared Tooling Wins
Both approaches benefit from Kotlin's excellent tooling: Gradle for builds, kotlinx.serialization for JSON, Ktor for HTTP, SQLDelight for databases, Koin for dependency injection, and Kotlin coroutines for async work. The difference is purely at the UI layer. For a deeper comparison of how Kotlin stacks up against Swift as a language, see our Swift vs Kotlin analysis.
Cost, Timeline, and Real-World Decision Framework
Let us talk money and time, because that is what actually drives most framework decisions.
Initial Development Cost
For a mid-complexity app (15 to 25 screens, API integration, local storage, push notifications, authentication), here is what we see in 2026:
- KMP with native UIs: $120K to $200K. You are building two UIs (SwiftUI + Compose) and one shared logic layer. The logic sharing saves 25 to 40% compared to two fully native apps, but you still need platform-specific UI work.
- Compose Multiplatform: $70K to $130K. A single team writes one UI and one logic layer. The savings come from eliminating the SwiftUI development entirely. Expect to spend 10 to 15% of the budget on iOS-specific polish and native interop for platform features.
- Two fully native apps (no sharing): $180K to $300K. For reference, this is what it costs to build the same app separately in SwiftUI and Jetpack Compose with no code sharing at all.
Ongoing Maintenance
KMP maintenance is predictable. Platform SDK updates affect only the platform-specific UI layers. Kotlin version upgrades affect the shared module but rarely require UI changes. When Apple introduces new SwiftUI APIs or Google launches new Compose features, each platform team can adopt them immediately without waiting for framework support.
CMP maintenance has an additional variable: JetBrains' release cycle. When Apple or Google introduces new platform features, CMP needs to add support or provide interop mechanisms. JetBrains has been responsive (the Compose Multiplatform 1.7+ releases tracked Jetpack Compose releases closely), but there is always a lag. If Apple announces a major new iOS interaction pattern at WWDC, CMP support might arrive weeks or months later. With KMP and native UIs, your iOS team can adopt it on day one.
Decision Framework
Choose KMP (shared logic only) when your app needs pixel-perfect native UX on each platform, when you have existing native mobile teams, when platform-specific features (ARKit, HealthKit, Android Auto, Wear OS) are core to the experience, or when you are adding code sharing to an existing native app incrementally. Companies like Netflix, Cash App, and Philips chose this path because native UI quality was non-negotiable.
Choose Compose Multiplatform when you are building a new app from scratch with a small team, when consistent cross-platform UI is acceptable (B2B tools, internal apps, content apps, MVPs), when your team is already strong in Kotlin/Compose, or when budget constraints make maintaining two UI codebases impractical. JetBrains' own tools (Toolbox, Space) use CMP, and companies like McDonald's have adopted it for specific product lines.
For teams evaluating the broader cross-platform landscape, including React Native and Flutter, our KMP vs React Native vs Flutter comparison covers those options in detail.
The Hybrid Path and Our Recommendation
Here is something most articles about KMP vs CMP miss: you do not have to choose one or the other for your entire app. The most effective production strategy in 2026 is a hybrid approach, and it is what we recommend to most of our clients.
Start with KMP as the foundation. Structure your project with a shared Kotlin module for networking, data persistence, domain logic, and state management. This shared module works identically regardless of whether you later choose native UIs or Compose Multiplatform for the view layer. You are never locked in at the logic level.
For the UI, evaluate screen by screen. Settings screens, list views, forms, and CRUD interfaces are perfect candidates for Compose Multiplatform. They are straightforward, they do not need platform-specific behavior, and sharing them saves significant development time. Camera interfaces, map integrations, platform-specific animations, and screens that rely on native SDK features should use native UIs (SwiftUI or UIKit on iOS, Jetpack Compose on Android). CMP's native interop makes this mix-and-match approach practical.
This hybrid path gives you the cost efficiency of shared UI where it makes sense and the platform fidelity of native UI where users will notice. It also de-risks the project: if CMP's iOS rendering does not meet your quality bar for a specific screen, you can drop to native for that screen without rearchitecting anything.
The Kotlin ecosystem is the real winner here. Whether you go pure KMP, pure CMP, or hybrid, you are writing Kotlin. Your team builds deep expertise in one language. Your tooling is consistent. Your shared logic module works in every scenario. That is a level of flexibility that no other cross-platform ecosystem offers today.
If you are planning a mobile project and trying to figure out where KMP, CMP, or a hybrid approach fits your requirements and budget, we can help. We have shipped production apps using all three strategies and can give you an honest technical assessment specific to your use case. Book a free strategy call and let us map out the right architecture together.
Need help building this?
Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.