Key Takeaways
- Kotlin Multiplatform (KMP) enables teams to share business logic and application architecture across platforms like iOS, Android, desktop, and web, while retaining the ability to build fully native user interfaces for optimal performance and user experience.
- Unlike “all-or-nothing” frameworks that require a complete rewrite, KMP supports gradual adoption. This allows development teams to incrementally introduce shared code into existing native Android and iOS projects, mitigating risk and allowing teams to upskill over time.
- By unifying business logic in a single Kotlin codebase, organizations can significantly reduce engineering costs, eliminate duplicated effort, and streamline development processes between otherwise separate Android and iOS teams.
- KMP avoids the performance overhead common in other cross-platform tools by compiling to native binaries and utilizing native UI toolkits, resulting in applications that deliver a fluid, native-like performance and feel.
- KMP provides flexibility when designing architecture, so that teams can decide precisely what to share: they can start by sharing only business logic while keeping native UIs or extend sharing to the UI layer itself using Compose Multiplatform.
Introduction
“Consistency is key” is a phrase often heard in the context of distributed systems, but also true in mobile and web application development. In a world where a single application needs to run seamlessly on multiple platforms, maintaining consistency across them is not just a goal, but a necessity. For years, developers have faced a difficult choice: build separate native applications for each platform, or adopt a cross-platform framework.
Developing natively for Android and iOS has traditionally required doubling resources: two codebases, two engineering teams, and double effort to keep features and business logic in sync. When apps require a consistent UI and identical business logic, it follows that they share the code that powers them.
This need gave rise to powerful cross-platform tools like Flutter and React Native. While highly effective, these tools often come with significant trade-offs. They typically require developers to use different UI rendering engines (Flutter) or use a bridge (React Native), which can introduce a performance penalty compared to native code.
In this situation, KMP offers a unique approach. Rather than replacing the native platform SDKs, KMP works with them, allowing developers to share common code with straightforward idiomatic access to the platform’s API. This specifically means you can create a KMP app retaining each platform’s look and feel by using the native UI toolkits, similarly to React Native. But you can also use Compose Multiplatform to go Flutter’s way and share the UI implementation, albeit at the cost of it not looking “native” on iOS.
In summary, when paired with Compose Multiplatform, KMP provides a compelling use case: compiling to native code for excellent performance, similar to Flutter, and retaining the option to use native UI toolkits, a flexibility also found with React Native.
KMP is emerging as a powerful alternative for cross-platform development, offering a path to share code without sacrificing the performance and feel of a native application. With KMP being an alternative, it comes with its own set of trade-offs and this article dives deeply into those.
While this article focuses primarily on Android and iOS development, KMP’s vision is even broader. It can be used to build desktop applications (Windows, macOS, Linux), web (using Kotlin/JavaScript), and even server-side applications, all from the same shared logic.
What is Kotlin Multiplatform (KMP)?
KMP allows development teams to write and share code across different platforms while still providing the option to build native user interfaces thanks to Compose Multiplatform. It is not an “all-or-nothing” framework that abstracts away the platform. Instead, it’s a sophisticated tool that allows you to share the parts of your application that are platform-agnostic, while keeping the platform-specific parts truly native. Android developers can write UI code in Kotlin and iOS developers can write UI code in Objective-C or Swift. But this does not mean that the UIs can only be built using native interfaces, which is an important distinction. KMP offers the flexibility to build the UIs as you wish.
How KMP Works
KMP has a specific project structure and the expect/actual
mechanism which makes it work cross-platform. A typical KMP project is divided into modules:
commonMain
contains the common code. This code is compiled once and shared across all target platforms. You can put the business logic, network calls, etc. in this module.androidMain
contains Android implementations. The UI for the Android device can be written in Kotlin in this module.iosMain
contains iOS implementations. The UI for the iOS device can be written in Swift or Objective-C.
The expect
/actual
keywords are the bridge between the common and platform-specific implementations. In commonMain
, you can expect a class or function to exist, defining its API. Then, in androidMain
and iosMain
, you provide the actual platform-specific implementation for that declaration. For example, you might expect a function to generate a unique identifier (UUID) in commonMain
, and then provide the actual implementation using Android’s UUID.randomUUID()
in androidMain
and iOS’s NSUUID().uuidString
in iosMain
.
Using the above constructs, the applications can be built simultaneously for cross-platform without sacrificing application performance.
Kotlin Multiplatform Benefits
Reduced Engineering Costs
It’s a given that unifying architecture and enabling the same developers to write code for multiple platforms can significantly reduce engineering costs. By placing business logic, networking, etc., in a shared commonMain
module, you eliminate the need to implement and test the same feature twice. This leads to a direct de-duplication of effort. This also reduces platform-specific bugs, leading to a more robust and reliable product. Furthermore, it streamlines the quality assurance process, as the core logic only needs to be tested once. An important callout that this benefit is offered by Flutter and React Native as well. KMP has no advantage over the other technologies in this aspect.
Native Performance
Unlike other cross-platform tools, KMP lets developers build UIs using the platform’s native tools. The shared Kotlin code is compiled down to the target platform’s expected format with JVM bytecode for Android and native binaries for iOS. There is no interpretation layer at runtime, unlike React Native, allowing the application to achieve native-like performance.
Gradual Adoption
While Flutter (which uses Dart) and React Native (which uses Typescript or Javascript) need an “all-or-nothing” adoption, such is not the case with Kotlin Multiplatform. It can be introduced gradually in the code base and the transition can be smoother. You can introduce KMP incrementally into your existing native applications, which helps ensure they remain stable throughout the process. A common starting point is to migrate a single feature or a specific layer into a shared KMP module.
Natural progression for Android teams
With Google officially endorsing Kotlin as the primary language for Android development, most Android teams are already building with it. For these teams, the transition to KMP has a significantly low barrier of entry.
Flutter vs. React Native vs. KMP: A Comparison
While all three technologies enable cross-platform development, they operate on different principles, especially regarding the user interface (UI) and overall philosophy. The following table summarizes the main differences we discussed above.
Feature | Flutter | React Native | Kotlin Multiplatform (KMP) |
Language | Dart | JavaScript / TypeScript | Kotlin |
UI Rendering | Renders its own UI with Skia engine | Controls native UI components via a JS Bridge | Can use Native UI (SwiftUI/ Compose) or a Shared UI (Compose Multiplatform) |
Performance | Excellent, compiles to native code, no bridge | Good, but the JavaScript bridge can be a bottleneck | Excellent, compiles to platform-native formats with no bridge |
Adoption | Full commitment | Full commitment | Gradual adoption |
Current State of KMP and Compose Multiplatform for iOS
Kotlin has historically never been used to develop iOS applications. But with KMP and Compose Multiplatform, it is now possible.
For a long time, the KMP story on iOS was “share your logic, build your UI natively”. While a powerful approach, it still meant UI development was a platform-specific task. With the stable 1.8.0 release, this changed. As of May 6, 2025, Compose Multiplatform for iOS has reached a stable, production-ready milestone.
This milestone is a big win for the KMP ecosystem. Jetpack Compose is Google’s modern, declarative UI toolkit for Android. With Compose Multiplatform, you can now use the exact same Kotlin code to define your UI for both Android and iOS. This means you can share not just business logic, but the UI itself. The framework now provides feature parity with Jetpack Compose for iOS, making it a viable option for new projects. In my view, Compose Multiplatform 1.8.0 has not only value for iOS development, but also fulfills the real value proposition of KMP with developers now being able to bootstrap the entire application.
Furthermore, the option to mix and match using native Swift/UIKit for some screens and Compose for others offers ultimate flexibility. To this aim, you rely on specific wrapper components provided by the framework that leverages SwiftUI/UIKit interoperability. For example, to use a Compose Multiplatform screen within a native SwiftUI app, wrap your Composable UI in a ComposeUIViewController
. Then, within the SwiftUI code, create a struct for the UIViewControllerRepresentable
protocol which will manage the controller. To use a native SwiftUI screen within the Compose UI, host the SwiftUI view inside a UIHostingController
, which can be directly embedded into a Compose layout using the UIKitView
composable.
The general idea is that whenever a mix and match approach is taken, there will be some controllers which make it possible to embed the different UI approaches being applied in the app. While there may be a steep learning curve involved, this approach still offers significant flexibility.
Big Users of Kotlin Multiplatform
KMP is not just a theoretical concept, it is being used in production by major global companies like Netflix, McDonald’s, and Philips.
Netflix is known as an early and significant adopter of KMP since they adopted it in October 2020. They used Kotlin Multiplatform to unify business logic across their applications, ensuring that features behave identically for all users, regardless of the device. They also used it for their internal “Prodicle” application, which supports the physical production of TV and film projects.
Our Android and iOS studio apps have a shared architecture with similar or in some cases identical business logic written on both platforms – Netflix.
Netflix was able to achieve a fifty percent decoupling of code from the underlying platform. Looking into the future, Netflix also talked about the possibility of evolving their studio apps into a thin UI layer which shares the same business logic written in KMP.
McDonald’s started using KMP (called KMM in earlier versions) when they introduced in-app payments into their app. After validating this approach, they expanded their use of KMP to other services.
Integrating KMM into the application flow allows us to develop the parsing and storage logic within one location, in addition to the business logic required to properly display the localized data and products on each platform – McDonald’s.
For example, to handle the different requirements for customers in various international locales, they centralized the logic for managing locale-specific products and data into a shared KMP module. Here, they introduced KMP into their business logic which would handle locale and device specific products and data.
Ultimately, McDonald’s rewrote their entire application to use KMP. With this strategic shift they merged their separate Android and iOS teams into a more unified and efficient mobile team.
Philips adopted KMP in 2018 as a means to move away from native development. Philips utilizes Kotlin Multiplatform to develop a shared SDK for device communication and data synchronization for their connected consumer and personal health products, enabling mobile app connectivity for devices like toothbrushes and air purifiers. Using KMP, they were able to keep a shared business logic.
There was so much difference in the BLE interfaces that you cannot come up with a design that matches them both. So that part we will keep on doing in a native way – Philips.
They initially faced some problems with Bluetooth APIs for Bluetooth Low Energy (BLE). To solve this, they kept native implementations for the Bluetooth stack, which goes to show how developers are not locked in KMP for all of their codebase.
We see that KMP is starting to pick up now with more companies adopting it. Companies are starting out slow and then ramping up their use cases as they start to see the benefits. I would recommend checking out all these case studies, because I only touched upon a select few.
Challenges and Considerations
While Kotlin Multiplatform presents a promising approach to cross-platform development, it’s important to acknowledge KMP’s current limitations.
Ecosystem Maturity
A primary challenge is the smaller developer community and support ecosystem when compared to existing tools like Flutter and React Native. While core functionalities are well-supported, finding KMP-ready libraries for highly specific needs, such as advanced Bluetooth interactions or background services, may still require writing platform-specific implementations as we saw in Philips’ case. This can sometimes mean that developers need to create their own wrappers around native solutions which is not ideal.
Learning Curve for iOS Teams
For iOS teams, there can be a learning curve associated with adopting Kotlin and the Gradle build system, which are standard in the Android ecosystem but new to most iOS developers.
Kotlin/Native Interoperability
The interoperability between Kotlin/Native and Swift/Objective-C has its own limitations. Kotlin/Native provides indirect interoperability with Swift through Objective-C. For example, some Kotlin language features may not have a direct equivalent in Objective-C, requiring developers to know of these differences during development. This requirement can become a big hurdle, because most developers would not know this prior to beginning development. Generics is one example, where type information is lost during translation. Developers need to be mindful of the types being passed and instead have checks around this.
Tooling and Development Workflow
While the tooling is improving consistently, it is still not as seamless as the native development tooling currently. There are plugins for KMP that make it easier and are being actively developed by JetBrains.
While the challenges are not limited or to be glanced over, this environment is rapidly changing. It’s fair to say that support for Kotlin itself is mature and continues to grow, and the KMP community is a direct beneficiary of this trend. As adoption increases, so too will the amount of shared knowledge and open-source libraries.
Conclusion
Cross-platform development has always been an exercise in balancing trade-offs: development efficiency versus native performance and look-and-feel. With Kotlin Multiplatform, these trade-offs are somewhat reduced. You gain the efficiency of a shared codebase while delivering performance that feels almost as good as native.
While core functionalities are well-supported, finding KMP ready libraries for highly specific needs, like advanced BLE interactions or background location services, may still require writing platform-specific implementations. This does pose a problem as applications which require all these features cannot be built only using KMP. But as mentioned before, it is an iterative process and since the KMP development is active, better support will be introduced.
KMP offers a flexible and powerful path forward, allowing teams to build consistent, high-performance applications for a multi-platform world without leaving their native roots behind. The support for Kotlin is strong, and its multi-platform capabilities are only set to grow from here.