What Is Kotlin Multiplatform and How It Works

Ever wanted to write code once and run it everywhere without sacrificing native performance? Kotlin Multiplatform (KMP) makes this possible.
Developed by JetBrains, Kotlin Multiplatform is a cross-platform app development tool that lets developers share business logic across Android, iOS, web applications, and desktop platforms while keeping native UI and platform-specific features. Unlike other frameworks promising “write once, run anywhere,” KMP takes a pragmatic approach:
- Share what makes sense (data models, networking, business logic)
- Keep platform-specific code where it matters (UI, hardware access)
This modern mobile development framework sits between fully native and hybrid approaches. It uses a single codebase for common code while allowing platform-independent implementations where needed.
Through this article, you’ll learn how KMP works, its architecture, how to set up projects, implement platform-specific code, and follow real-world patterns used by companies like Netflix, Philips, and Square that have adopted this technology to boost developer productivity and reduce app development costs.
What Is Kotlin Multiplatform?
Kotlin Multiplatform is a feature of Kotlin that enables code sharing across multiple platforms like Android, iOS, desktop, and web. Developers can write common logic once and use it across platforms while still accessing platform-specific APIs. It helps reduce duplication, improve consistency, and speed up cross-platform app development.
Technical Foundations of Kotlin Multiplatform

Kotlin Multiplatform (KMP) lets developers share code across platforms while maintaining native performance. It’s not just another framework—it’s a fundamental shift in cross-platform development.
Expect and Actual Declarations
The core of KMP’s architecture lies in its expect/actual mechanism. This clever system enables true code sharing while respecting platform differences.
// In common code
expect class DateFormatter() {
fun formatDate(timestamp: Long): String
}
// In Android code
actual class DateFormatter() {
actual fun formatDate(timestamp: Long): String {
return SimpleDateFormat("yyyy-MM-dd").format(Date(timestamp))
}
}
// In iOS code
actual class DateFormatter() {
actual fun formatDate(timestamp: Long): String {
let date = NSDate(timeIntervalSince1970: timestamp)
// iOS-specific formatting
return formatter.string(from: date as Date)
}
}
The common module defines what you need, platform modules implement how it works. Simple yet powerful.
Common Modules Structure
KMP projects organize code into source sets. The commonMain source set contains platform-independent logic that works everywhere.
This shared business logic forms the foundation of your application. Think data models, business rules, networking logic—all written once.
Platform-specific code lives in dedicated source sets (androidMain, iosMain). This structure creates clear boundaries between shared and platform-specific implementations.
Platform-Specific Implementations
JetBrains designed KMP to embrace platform differences when necessary. Not everything should be shared.
For UI components or hardware access, you’ll write platform-specific code. KMP doesn’t force you into uncomfortable abstractions—it lets each platform shine.
Kotlin/Native Compiler Technology
The magic happens in the Kotlin/Native compiler. It takes your Kotlin code and translates it to run natively on non-JVM platforms.
The compiler uses LLVM backend integration to generate optimized native binaries. Your iOS code runs truly natively—no interpretation or bridging layers.
Memory management differs across platforms. JVM uses garbage collection, while Kotlin/Native initially used reference counting (now moving toward a unified memory model with the new memory manager).
Gradle Build System Integration
KMP leverages Gradle for its multiplatform project setup. The Kotlin Multiplatform Gradle plugin handles the complexity of targeting multiple platforms.
A typical KMP build file defines source sets and target platforms:
kotlin {
android()
ios()
sourceSets {
commonMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
}
androidMain {
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
}
}
}
}
This configuration manages dependencies across platforms—shared libraries in common code, platform-specific libraries where needed.
Creating a Kotlin Multiplatform Project

Starting with KMP requires understanding its unique project organization and tools.
Project Structure and Organization
The heart of any KMP application is its common code modules. These modules contain your shared business logic, data models, and algorithms.
Platform-specific modules connect your shared code to each target platform. They implement expected declarations and add platform-specific features.
Test modules let you verify common code works consistently across platforms. Write tests once, run everywhere.
Setting Up the Development Environment
You’ll need:
- IntelliJ IDEA or Android Studio with Kotlin plugin
- Xcode (for iOS development)
- JDK 8 or newer
- Kotlin Multiplatform Mobile plugin
IDE configuration is straightforward with modern tooling. The KMP plugin handles most of the setup automatically.
Each platform requires its own SDK. Android needs Android SDK, iOS needs Xcode and iOS SDK, and so on.
Creating Shared Code
Writing platform-agnostic logic requires focus on Kotlin‘s common standard library. This subset works identically across all platforms.
// Platform-independent networking repository
class UserRepository(private val api: UserApi) {
suspend fun getUsers(): List<User> {
return api.fetchUsers()
}
suspend fun saveUser(user: User): Result<Unit> {
return try {
api.createUser(user)
Result.success(Unit)
} catch (e: Exception) {
Result.failure(e)
}
}
}
This code runs unchanged on Android, iOS, desktop, or web.
Kotlinx libraries provide cross-platform solutions for common tasks. Kotlinx.coroutines offers structured concurrency across platforms. Kotlinx.serialization handles JSON parsing. Ktor client works everywhere for networking.
When platform-specific functionality is needed, implement the expect/actual pattern. The common code expects functionality, platform code delivers it.
Code sharing works best when you focus on business logic rather than UI. Aim for 50-70% shared code in typical applications.
The mobile app development tool ecosystem for KMP continues to grow. Libraries like SQLDelight provide single codebase database solutions for multiple platforms.
Platform-Specific Implementation
Android Implementation

Integrating common code in Android projects works seamlessly. Your shared Kotlin multiplatform modules appear as regular dependencies in Android projects.
// In build.gradle
dependencies {
implementation project(':shared')
}
Android-specific features sit alongside shared code naturally. The JVM language compatibility makes this integration particularly smooth.
class AndroidMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Access shared repository
val repository = getSharedRepository()
// Use Android-specific components
val viewModel = ViewModelProvider(this)[UserViewModel::class.java]
viewModel.loadUsers(repository)
}
}
Performance considerations remain important. Kotlin/JVM code runs efficiently on Android with minimal overhead compared to pure Java.
iOS Implementation

Swift/Objective-C interoperability with Kotlin Native enables smooth integration. Kotlin classes are exposed to Swift with proper naming conventions.
// Using Kotlin code from Swift
import SharedKit
class iOSViewController: UIViewController {
let repository = UserRepositoryHelper().createRepository()
override func viewDidLoad() {
super.viewDidLoad()
// Call Kotlin code
repository.getUsers { users, error in
if let users = users {
self.updateUI(with: users)
}
}
}
}
CocoaPods integration simplifies dependency management for iOS developers. The Kotlin Multiplatform Gradle plugin generates pods automatically.
# In Podfile
target 'iOSApp' do
pod 'shared', :path => '../shared'
end
Memory management between Kotlin and iOS requires attention. Kotlin/Native’s memory model differs from Swift’s ARC system. The new memory manager improves this situation considerably.
Web and Desktop Implementations
JavaScript and browser targets expand KMP beyond mobile. Kotlin/JS transpiles your code to JavaScript for web applications.
// Common code running in browser
window.onload = {
val userService = UserService()
userService.getUsers().then { users ->
document.getElementById("user-list")?.innerHTML = users.joinToString { it.name }
}
}
JVM and desktop applications benefit from KMP too. Write business logic once, use it in your desktop apps built with JavaFX, TornadoFX, or Compose Desktop.
Native desktop targets like Windows, macOS, and Linux run efficiently with Kotlin/Native. Compose Multiplatform brings modern UI development to all platforms.
Real-World Patterns and Best Practices
Architecture Patterns for Multiplatform Projects
Clean Architecture implementation works exceptionally well with KMP. The strict separation of concerns aligns perfectly with multiplatform development.
// Domain layer (common)
class GetUserUseCase(private val repository: UserRepository) {
suspend operator fun invoke(userId: String): User {
return repository.getUser(userId)
}
}
// Data layer (common with expect/actual for platform specifics)
interface UserRepository {
suspend fun getUser(id: String): User
}
MVI/MVVM patterns across platforms create consistency. The unidirectional data flow of MVI works particularly well for shared state management.
// Shared ViewModel pattern
class UserListViewModel(
private val getUsersUseCase: GetUsersUseCase
) : ViewModel() {
private val _state = MutableStateFlow<UsersState>(UsersState.Loading)
val state: StateFlow<UsersState> = _state
fun loadUsers() {
viewModelScope.launch {
try {
val users = getUsersUseCase()
_state.value = UsersState.Success(users)
} catch (e: Exception) {
_state.value = UsersState.Error(e.message ?: "Unknown error")
}
}
}
}
Repository pattern for data access creates clear boundaries between UI and data sources. Implement repositories in common code, with platform-specific data source implementations.
Testing Strategies
Testing common code is straightforward. Use multiplatform testing libraries like kotlin.test to write unit tests that run on all platforms.
// Common test
class UserRepositoryTest {
@Test
fun testGetUsers() = runTest {
val repository = FakeUserRepository()
val users = repository.getUsers()
assertEquals(3, users.size)
assertEquals("Alice", users[0].name)
}
}
Platform-specific testing approaches complement common tests. For Android, use JUnit and Robolectric. For iOS, XCTest integrates with your Kotlin tests.
Integration testing across boundaries verifies everything works together. Test API calls, database access, and platform interfaces with realistic scenarios.
Dependency Injection
Multiplatform DI libraries like Koin work across platforms. Define modules in common code with platform-specific implementations.
// Common Koin module
val commonModule = module {
single { NetworkClient() }
single { UserRepository(get()) }
}
// Platform-specific module
val androidModule = module {
single { AndroidDatabaseDriver() }
}
Manual DI approaches offer simplicity. Create factories that construct dependencies with platform-specific components.
// Manual DI with factory pattern
class ServiceLocator {
val networkClient = NetworkClient()
val databaseDriver = createPlatformDatabase()
val userRepository = UserRepository(networkClient, databaseDriver)
expect fun createPlatformDatabase(): DatabaseDriver
}
Platform-specific DI integration connects your shared DI solution to platform frameworks. On Android, integrate with Hilt or Dagger. On iOS, use property wrappers or manual DI.
The target multiple platforms approach of KMP reduces duplicate code while respecting platform differences. This balance makes Kotlin Multiplatform distinct from “write once, run anywhere” solutions.
Libraries and Ecosystem
Official Kotlin Multiplatform Libraries
Kotlinx libraries form the foundation of KMP development. They solve common problems across platforms with elegant API design.
Kotlinx.coroutines brings structured concurrency to all platforms. Write asynchronous code that looks synchronous:
suspend fun fetchUsers(): List<User> = coroutineScope {
val usersDeferred = async { api.getUsers() }
val statsDeferred = async { api.getUserStats() }
val users = usersDeferred.await()
val stats = statsDeferred.await()
users.map { it.copy(stats = stats[it.id]) }
}
Kotlinx.serialization handles JSON parsing without reflection. This matters for Kotlin/Native and Kotlin/JS targets:
@Serializable
data class User(
val id: String,
val name: String,
val email: String
)
// Parse JSON on any platform
val user = Json.decodeFromString<User>(jsonString)
Ktor provides a common HTTP client with platform-specific engines. Network calls work identically across platforms:
val client = HttpClient()
suspend fun getUser(id: String): User {
return client.get("https://api.example.com/users/$id").body()
}
SQLDelight generates type-safe Kotlin APIs from SQL. Your database code runs on Android, iOS, and desktop:
// SQL
CREATE TABLE User (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL
);
// Generated Kotlin
data class User(
val id: String,
val name: String,
val email: String
)
// Use in common code
database.userQueries.getAllUsers().executeAsList()
Third-Party Libraries
Popular multiplatform libraries continue growing. Koin for dependency injection, Multiplatform Settings for preferences storage, and Decompose for navigation work across platforms.
Evaluating library compatibility requires checking supported targets. Not every library works on all platforms yet.
// In build.gradle.kts
kotlin {
sourceSets {
commonMain {
dependencies {
implementation("io.insert-koin:koin-core:3.3.0")
implementation("com.russhwolf:multiplatform-settings:1.0.0")
implementation("com.arkivanov.decompose:decompose:1.0.0")
}
}
}
}
Creating multiplatform libraries follows similar patterns to applications. Define common interfaces, implement platform-specific code when needed, and publish with proper Gradle configuration.
Tools for Multiplatform Development
IDE tools and plugins streamline development. JetBrains’ IDEs offer first-class support for KMP:
- IntelliJ IDEA/Android Studio: Complete project templates, code completion, and refactoring
- Kotlin Multiplatform Mobile plugin: iOS simulator integration and CocoaPods support
- Compose Multiplatform plugin: Preview UI components across platforms
Debugging across platforms works directly in the IDE. Set breakpoints in shared code and debug Android, iOS, or desktop applications from a single environment.
Profiling and performance tools help optimize multiplatform code. Each platform has native profilers, but tools like Kotlin/Native Memory Profiler specifically target KMP applications.
The KMP community support grows daily. Active GitHub repositories, Stack Overflow tags, and dedicated Discord channels provide help for newcomers.
KMP’s roadmap shows steady progress toward stable status. JetBrains continues investing in mobile development efficiency through Kotlin.
// Future KMP code might look even simpler
@Composable
fun UserList(users: List<User>) {
LazyColumn {
items(users) { user ->
UserCard(user)
}
}
}
Single codebase multiple platforms development reduces maintenance costs. Teams share knowledge instead of duplicating work across platform-specific codebases.
Kotlin Multiplatform adoption continues growing among major companies. Businesses recognize the potential cost savings and improved development workflow.
FAQ on Kotlin Multiplatform
How does Kotlin Multiplatform compare to React Native and Flutter?
KMP focuses purely on code sharing, not UI frameworks. React Native uses JavaScript with native bridges, and Flutter draws its own UI. KMP lets you maintain native UIs with shared business logic, offering better native performance and integration while potentially sharing 50-70% of non-UI code.
What platforms does Kotlin Multiplatform support?
KMP supports:
- Android (via JVM)
- iOS (via Kotlin/Native)
- Web (via Kotlin/JS)
- Desktop (Windows, macOS, Linux)
- Backend (JVM)
- WebAssembly (experimental)
This multi-target compilation flexibility makes it suitable for varied development needs.
What’s the difference between KMM and KMP?
Kotlin Multiplatform Mobile (KMM) is a subset of Kotlin Multiplatform (KMP) specifically targeting mobile platforms (Android and iOS). KMP is the broader technology covering all platforms including web and desktop. JetBrains initially promoted KMM to focus on the most common use case.
What’s the learning curve for Kotlin Multiplatform?
For Android developers familiar with Kotlin, the learning curve focuses on the expect/actual mechanism and Gradle configuration. iOS developers face a steeper curve learning Kotlin. The build system complexity and multiplatform project setup require time investment for all teams.
What companies use Kotlin Multiplatform in production?
Several major companies have adopted KMP:
- Netflix
- Philips
- Square
- VMware
- Cash App
- Autodesk
- Touchlab
- JetBrains
The growing KMP community support shows increasing industry confidence in this approach.
What percentage of code can be shared with Kotlin Multiplatform?
Most projects achieve 50-70% code sharing with KMP. Business logic, networking, data processing, and algorithms share well. UI, platform-specific features, and hardware access typically remain platform-specific. The platform-independent code percentage varies by app type and architecture choices.
Does Kotlin Multiplatform require learning new programming languages?
Android developers only need to know Kotlin. iOS developers need to learn Kotlin basics but can still write Swift/Objective-C for UI. The expect/actual mechanism requires understanding how to structure code for multiplatform projects, but no additional languages are necessary for implementation.
What are the main benefits of using Kotlin Multiplatform?
Key benefits include:
- Reduced development and maintenance costs
- Native performance and UX
- Code consistency across platforms
- Smaller team size requirements
- Platform-specific API access
- Gradual adoption possibility
- Strong type safety
- Modern language features
What libraries are available for Kotlin Multiplatform?
The KMP ecosystem includes:
- Kotlinx.coroutines for async programming
- Kotlinx.serialization for data parsing
- Ktor for networking
- SQLDelight for database access
- Koin for dependency injection
- Multiplatform Settings for preferences
- Decompose for navigation
- Compose Multiplatform for UI (newer)
Conclusion
What is Kotlin Multiplatform at its core? It’s a pragmatic approach to cross-platform development that respects platform differences while eliminating redundant code. After exploring its architecture, implementation details, and ecosystem, we can see why KMP adoption continues growing among development teams.
The framework’s greatest strength lies in its flexibility. Unlike other mobile app development tools, KMP doesn’t force uncomfortable compromises:
- Share what makes sense – business logic, networking, data processing
- Keep what should be native – UI components, platform-specific features
- Choose your architecture – works with modern patterns like Clean Architecture and MVI
KMP isn’t perfect—the build systems complexity and relative ecosystem youth present challenges. Yet JetBrains’ technology continues maturing rapidly, with the KMP roadmap showing promising stability improvements.
For teams tired of maintaining duplicate codebases while still demanding native performance, Kotlin Multiplatform offers a compelling middle ground between platform-specific implementation and development workflow efficiency. The programming language features that make Kotlin loved by developers now extend beyond Android to truly multi-target compilation.
- Kotlin Regex: A Guide to Regular Expressions - April 22, 2025
- What Is the Kotlin Enum Class? Explained Clearly - April 22, 2025
- Managing E-commerce Inventory with Data Tracking - April 22, 2025