Kotlin Multiplatform (KMP) is a JetBrains technology that compiles shared Kotlin code for iOS, Android, Web, and Desktop. Unlike Flutter and React Native, KMP does not replace native UI — shared logic is extracted into a shared module, while each app's interface remains native. Kotlin Multiplatform documentation — the main reference for configuring modules and the expect/actual mechanism.
Key Takeaways
Kotlin Multiplatform is a cross-compilation technology that allows writing shared code in Kotlin and compiling it for different platforms: JVM (Android), LLVM (iOS, macOS, watchOS), JavaScript (Web), and native binaries (Linux, Windows). KMP is not a UI framework — it solves the problem of reusing business logic, not interfaces.
The KMP architecture is built around a shared module — a Gradle module containing commonMain with platform-independent code and source sets for each target (androidMain, iosMain, desktopMain). According to JetBrains data for 2025, over 40% of new Kotlin projects use KMP to share code between platforms.
Kotlin Multiplatform Mobile (KMM) — the previous name for the iOS+Android mobile scenario. Since Kotlin 2.1+, the KMM term has been replaced by Kotlin Multiplatform, as the technology has expanded beyond mobile development. Netflix, McDonald's, and VMware use KMP in production to share code between mobile applications.
Expect/actual — the key KMP mechanism for working with platform-specific code. In commonMain, an expect declaration (function, class, property) is declared, and in each platform-specific source set (androidMain, iosMain), an actual implementation is provided. The compiler checks that for each expect, there is an actual in every target platform.
// commonMain — platform API declaration
expect fun getPlatformName(): String
expect class PlatformContext(val appVersion: String)
// androidMain — actual for Android
actual fun getPlatformName(): String = "Android \${Build.VERSION.SDK_INT}"
// iosMain — actual for iOS
actual fun getPlatformName(): String =
UIDevice.currentDevice.systemNameThe source set hierarchy in KMP allows creating intermediate levels: for example, iosArm64Main (physical iOS devices) and iosSimulatorArm64Main (simulator) with shared iosMain. Code from commonMain is available to all platforms, while code from iosMain is only available to iOS targets. This reduces duplication when the implementation differs not for each platform but for a group of platforms.
In practice, expect/actual is used for: accessing local storage (SharedPreferences vs NSUserDefaults), networking (HttpEngine per platform), file system access, cryptography, and analytics. JetBrains recommends minimizing the number of expect/actual declarations and moving as much code as possible to commonMain.
Shared module — a standard Gradle module with the org.jetbrains.kotlin.multiplatform plugin. It contains shared code in src/commonMain/kotlin/ and platform-specific implementations in src/androidMain/kotlin/ and src/iosMain/kotlin/. A KMP project also includes androidApp and iosApp, which depend on the shared module.
// build.gradle.kts — shared module
plugins {
kotlin("multiplatform")
id("com.android.library")
}
kotlin {
androidTarget()
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "shared"
isStatic = true
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:3.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-okhttp:3.1.0")
}
}
val iosMain by creating {
dependencies {
implementation("io.ktor:ktor-client-darwin:3.1.0")
}
}
}
}The Gradle configuration for KMP requires explicit declaration of iOS targets — x64 (Intel simulator), arm64 (physical devices), and simulatorArm64 (Apple Silicon simulator). A separate Apple framework is generated for each target. The kotlin("multiplatform") plugin automatically configures compilation for JVM and LLVM depending on the declared targets.
Ktor and kotlinx.serialization — standard KMP libraries that support shared code. Ktor provides an HTTP client with engines for each platform (OkHttp for Android, Darwin for iOS). kotlinx.serialization works on all platforms without expect/actual thanks to its multiplatform implementation in commonMain.
Kotlin/Native — a Kotlin compiler for native code via LLVM. For iOS, the shared module is compiled into an Apple framework (.framework) that is connected via Xcode. Calling shared code from Swift/Objective-C happens through generated Objective-C headers, so the shared module API must be compatible with Objective-C.
iOS integration limitations: Kotlin collections (List, Map) are converted to NSArray/NSDictionary. Functions with default parameters are not exported — overloads are needed. For suspend functions, callback-based methods are generated with @ObjCName and async/await support starting from Kotlin 2.0+.
// iOS app: calling shared module from Swift
import shared
class ViewModel: ObservableObject {
let repository = UserRepository()
func loadUsers() {
repository.fetchUsers(completionHandler: { result, error in
if let users = result as? [User] {
print("Users: \(users.count)")
}
})
}
}Shared module integration into Xcode happens via embed-and-framework — the generated .xcframework is added to the Xcode project. The Gradle plugin can automatically update the framework during build via embedAndSignAppleFrameworkForXcode. For testing on the simulator, an iosSimulatorArm64 or iosX64 binary is sufficient.
The choice between KMP, Flutter, and React Native depends on the priority: code reuse or full cross-platform. KMP provides native UI on each platform but requires two code bases for the interface. Flutter and React Native use a single UI but sacrifice nativity.
| Feature | KMP | Flutter | React Native |
|---|---|---|---|
| UI framework | Native (Android XML/Jetpack Compose + SwiftUI) | Dart + own Skia renderer | React + native components |
| Shared code | Business logic, networking, DB, validation | 100% except native plugins | 100% except native modules |
| Performance | Native (no middleware) | High (Skia Engine) | Medium (JSI Bridge) |
| iOS support | Kotlin/Native (excellent) | Excellent | Good |
| Entry barrier | Medium (Kotlin + native platforms) | Low (one language + one UI) | Low (JS/TS + React) |
When to choose KMP: the project requires high-performance UI (games, maps, animations), existing native code needs to be reused, the team already knows Kotlin and native platforms. When to choose Flutter/RN: MVP or startup with limited budget, a single-profile team, the UI does not require deep native customization.
The KMP tools ecosystem includes libraries for all application layers: networking (Ktor), serialization (kotlinx.serialization), database (SQLDelight), navigation (Decompose), DI (Koin), and data storage (multiplatform-settings). JetBrains supports Compose Multiplatform — a Kotlin UI framework that runs on all platforms.
// KMP Repository with SQLDelight + Ktor
class UserRepository(
private val httpClient: HttpClient,
private val db: AppDatabase
) {
suspend fun syncUsers(): List<User> {
val remote = httpClient.get("https://api.example.com/users")
.body<List<UserDto>>()
db.userQueries.replaceAll(remote.map { it.toDomain() })
return db.userQueries.selectAll().executeAsList()
}
}Compose Multiplatform — a UI framework for KMP based on Jetpack Compose. It allows writing interfaces in Kotlin for Android, iOS, Desktop, and Web. In 2025, Compose Multiplatform reached stable status for Android and Desktop; iOS target is in beta. For production projects with native UI, KMP's advantage remains the key difference from Flutter.
Frequently Asked Questions
KMM — the mobile scenario of KMP for iOS and Android. Since Kotlin 2.1+, JetBrains combined both terms into Kotlin Multiplatform, as the technology supports not only mobile platforms but also Desktop and Web. KMM projects continue to work, but they are now part of the overall KMP.
Yes. KMP compiles into an Apple framework via Kotlin/Native with Objective-C headers. SwiftUI imports this framework like any regular library. The shared module exports Kotlin classes and functions that are called from Swift with some limitations (for example, Kotlin collections are converted to Foundation types).
On iOS, the shared module is tested via Kotlin/Native tests in the iosTest source set. For UI tests, XCTest is used in Xcode with the imported framework. Kotlin tests are written in commonTest with kotlin.test and run on the iOS simulator via the iosSimulatorArm64Test Gradle task.
Main KMP libraries: Ktor (networking), kotlinx.serialization (JSON), SQLDelight (DB), Koin (DI), Decompose (navigation), multiplatform-settings (SharedPreferences/NSUserDefaults), Apollo GraphQL, Firebase (via KMP-NativeCoroutines). Compose Multiplatform provides UI for all platforms.
Yes. KMP is fully compatible with Gradle 8.5+. Starting from Kotlin 2.1, official plugins support Gradle 8. Configuration via build.gradle.kts with kotlin("multiplatform") requires Gradle 7.6+, but version 8.5 is recommended for optimal build performance.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also