
Taras Leskiv
9 min read - Mar 12, 2025
Is KMP Production Ready in 2025? A Real-World Migration Story
A recap of the GDG Lviv talks that I gave in March of 2025 (In Ukrainian). A short retrospective on rewriting TransFollow’s logistics app with Kotlin Multiplatform and shared UI.
As a mobile engineer on a six-person team, I needed to deliver an iOS version of TransFollow’s mature Android app without adding a dedicated iOS developers. We chose to rewrite the product with Kotlin Multiplatform and Compose Multiplatform with shared UI.
Six months later, this is the retrospective: the strengths, the weaknesses, and the rough edges of KMP in 2025.
The Good: Where KMP Works Well
If you come from an Android background, KMP feels natural and close to the metal instead of bridged.
- One language everywhere: Kotlin across platforms with
expect/actualinstead of plugin layers. - Desktop target accelerates iteration: JVM desktop builds are fast for UI mocks and testing; Compose Hot Reload (experimental) shortens feedback loops.
- Ecosystem is mostly there: Ktor, Coil, Koin, SQLDelight (plus Room KMP), and Sentry covered our needs.
- Shared UI is practical: Compose Multiplatform delivered Material 3 on Android and its own canvas on iOS. Platform-specific components (MapView, Camera) slot in via
UIKitView/AndroidView.
The Challenges
- Fast-moving toolchain: Version bumps across Kotlin, Compose, KSP, and libraries can conflict.
- iOS build times and memory load: Building the iOS framework is heavy; even an M1/32GB can hit limits on release builds.
- Objective-C interop friction: KMP outputs Objective-C today, so generics and API names can be verbose from Swift, and CocoaPods/c-interop errors are noisy.
The Rough Edge (now improving)
Fleet felt unfinished—large downloads and limited previews. JetBrains is now doubling down on Android Studio and IntelliJ for KMP, and Canary builds ship stable previews.
Tips for a smooth migration
- Write native code yourself: Define
expectin common code; implementactualwith platform APIs instead of depending on wrappers. - Master suspendCoroutine: Bridge callback-based native APIs (e.g., permissions) into coroutines cleanly using
suspendCoroutine. - Use SQLDelight: Room supports KMP now, but SQLDelight’s generated code stayed sturdier for us.
- Don’t force SwiftUI (yet): Sharing UI with Compose kept our small team fast; native UI can wait.
Verdict
KMP is production ready for small and mid-sized teams—especially if you already think in Kotlin. You move quickly, share most of the code (including UI), and keep developer satisfaction high. I would choose the same path again.
Slides from the talk
View the deck on SlideShare: kmp-state-in-2025-taras-leskiv-gdg-lviv-meetup-06-03-2025-pptx