Kotlin Multiplatform

Also known as: KMP

On this page 7

Kotlin Multiplatform (KMP) is a technology from JetBrains that lets developers write shared code in Kotlin once and compile it for several platforms, including Android, iOS, desktop, web and server, while keeping full access to each platform’s native APIs. In mobile app development it is used mainly to share business logic, networking, data storage and validation between Android and iOS apps, while the user interface can remain native or be shared as well.

Unlike frameworks that run an app inside a separate runtime, KMP compiles to each platform’s native format: JVM bytecode for Android, native binaries through Kotlin/Native for iOS, and JavaScript or WebAssembly for the web. This makes it possible to adopt it gradually inside existing apps, one module at a time, which is a key reason why many teams choose it over a full rewrite.

How Kotlin Multiplatform shares code

A KMP project is organized into source sets. The commonMain source set holds code that is compiled for every target, and platform source sets such as androidMain and iosMain hold code specific to one platform. Common code may use only multiplatform libraries and the Kotlin standard library, while platform code can call any Android or iOS API directly.

When common code needs a platform capability, the developer declares an expect declaration in common code and provides an actual implementation for each platform. For example, a common expect fun deviceName(): String gets one actual implementation using Android APIs and another using UIKit. Many teams prefer plain interfaces with dependency injection for the same purpose, keeping expect and actual for small, low-level pieces.

TargetCompiler backendOutputTypical use
Android and JVMKotlin/JVMJVM bytecodeAndroid apps, servers, desktop
iOS and macOSKotlin/Native (LLVM)Native framework for XcodeiOS apps and Apple platforms
WebKotlin/JS or Kotlin/WasmJavaScript or WebAssemblyBrowser applications
Desktop nativeKotlin/NativeNative executableCommand-line tools, Linux and Windows
Compilation targets and their output

Sharing logic versus sharing the user interface

KMP supports a spectrum of sharing, from a single shared module to an almost entirely shared app. The UI decision is the most important architectural choice, because it determines how native the app feels and how much code is reused.

ApproachWhat is sharedUser interfaceTypical code reuse
Single shared moduleOne area such as networking or validationNative on each platformLow, chosen for gradual adoption
Shared business logicData, domain and networking layersJetpack Compose and SwiftUIModerate to high for non-UI code
Shared logic and UIAlmost everything, using Compose MultiplatformOne Compose UI on all platformsHighest
Levels of code sharing with KMP

Compose Multiplatform, also from JetBrains, extends Jetpack Compose to iOS, desktop and web. It lets teams share screens as well as logic, while still allowing native SwiftUI or UIKit views where a platform-specific look or API is required. Teams that value a fully native iOS look often keep SwiftUI for screens and share everything beneath them.

Kotlin Multiplatform compared with other cross-platform frameworks

Kotlin Multiplatform is often compared with Flutter, React Native and .NET MAUI. The key difference is that KMP treats sharing as optional and native integration as the default, whereas most alternatives start from a shared UI layer.

TechnologyLanguageUI approachNative integration
Kotlin MultiplatformKotlinNative UI or Compose MultiplatformDirect calls to platform APIs
FlutterDartOwn rendering engine and widgetsThrough platform channels and plugins
React NativeJavaScript or TypeScriptNative components driven from JavaScriptThrough native modules
.NET MAUIC#Abstraction over native controlsThrough .NET bindings
KMP and neighboring cross-platform options

Because KMP produces ordinary Android libraries and iOS frameworks, an existing native app can consume a shared module like any other dependency. That makes it attractive for teams with established native codebases, while Flutter or React Native often suit greenfield apps that want one UI from the start.

Tooling, libraries and project setup

KMP projects are built with Gradle and developed mainly in Android Studio or IntelliJ IDEA, while Xcode is still needed to build, sign and run the iOS app. The shared code is delivered to iOS as an XCFramework, either directly or through Swift Package Manager or CocoaPods integration.

A mature ecosystem of multiplatform libraries covers the most common needs: Ktor for HTTP networking, kotlinx.serialization for JSON, kotlinx.coroutines for concurrency, SQLDelight or Room for local databases, and Koin for dependency injection. Choosing libraries with multiplatform support from the start avoids rewriting modules later.

  • Start with a stable, logic-heavy module such as networking or data validation.
  • Keep platform code thin and test shared logic with common unit tests.
  • Agree on iOS integration early, including how Swift developers consume the shared API.
  • Pin Kotlin and library versions across modules to avoid binary incompatibilities.

Limitations and practical pitfalls

KMP is production-ready, but it introduces trade-offs that teams should plan for. Most of them concern the iOS side, where Kotlin code is consumed from Swift.

PitfallEffectMitigation
Swift interoperability gapsSome Kotlin features look awkward in SwiftDesign a Swift-friendly API or use interop tools
Longer iOS build timesSlower feedback for iOS developersModularize and cache builds
Team skill imbalanceiOS developers must read and review KotlinShared ownership and training
Library gapsSome SDKs exist only for one platformWrap them behind interfaces in platform code
Debugging across languagesHarder tracing from Swift into KotlinUse IDE plugins for native debugging
Common pitfalls and mitigations

Another mistake is sharing too much too early. Code that differs between platforms by design, such as permission flows or platform-specific UI behavior, often becomes more complex when forced into common code.

Explained without jargon

Kotlin Multiplatform lets a team write the hidden parts of an app once and use them on both Android phones and iPhones. Think of a restaurant chain with one central kitchen. The recipes are the same everywhere, but each restaurant still decorates its dining room in its own way.

The shared kitchen is the app’s logic, such as loading data and doing calculations. The dining room is what users see and touch. This saves work and keeps both apps behaving the same way.

A typical use case

A mid-sized fitness company maintains separate Android and iOS apps, and the two versions often calculate training statistics slightly differently, which confuses users who switch phones. The team moves the statistics engine, the API client and the offline database into a Kotlin Multiplatform module, while keeping the existing Jetpack Compose and SwiftUI screens.

Over two releases, about half of the non-UI code becomes shared, and both apps now produce identical results from the same tested logic. New features in the data layer are written once, and the iOS developers consume them through an XCFramework added with Swift Package Manager. The company reduces duplicated bug fixes without rewriting either app or changing how they look.