Kotlin Multiplatform for Enterprise Mobile Apps

Kotlin Multiplatform (KMP) lets you share business logic between iOS and Android while keeping native UI. This guide covers architecture, shared code strategies, the expect/actual mechanism, Compose Multiplatform, and how enterprises are adopting KMP.

Kotlin Multiplatform for Enterprise Mobile Apps

Key Takeaways

  • KMP shares business logic (50-70%) while iOS stays SwiftUI and Android stays Jetpack Compose
  • Shared code compiles to native binaries — no runtime performance penalty
  • Expect/actual pattern handles platform differences elegantly
  • KMP libraries (Ktor, SQLDelight, Koin) cover networking, data, and DI without platform-specific code
  • Ideal for enterprises migrating from native apps — adopt incrementally, module by module

What Is Kotlin Multiplatform

Kotlin Multiplatform is a technology from JetBrains that enables writing shared code in Kotlin that compiles to platform-native binaries. Unlike React Native or Flutter, KMP doesn't mandate a shared UI framework — you write native UI (SwiftUI on iOS, Jetpack Compose on Android) and share the layers underneath.

The shared layer typically includes:

  • Data models and DTOs
  • API clients (networking)
  • Business logic and validation
  • Database queries and caching
  • Analytics event tracking
  • Feature flags and configuration

On iOS, the shared Kotlin code compiles to a native framework (via Kotlin/Native) that Swift code imports like any other dependency. On Android, it's standard Kotlin — zero overhead.

KMP Architecture

┌──────────────────────────────────────────┐
│          iOS App (Swift/SwiftUI)          │
│   ┌─────────────────────────────────┐    │
│   │  SwiftUI Views + Navigation     │    │
│   │  Platform-specific features     │    │
│   └──────────┬──────────────────────┘    │
│              │  uses                      │
│   ┌──────────▼──────────────────────┐    │
│   │  Shared KMP Module (.framework) │    │
│   │  ├─ Models                      │    │
│   │  ├─ API Client (Ktor)           │    │
│   │  ├─ Repository Layer            │    │
│   │  ├─ Use Cases / Business Logic  │    │
│   │  ├─ Local DB (SQLDelight)       │    │
│   │  └─ DI (Koin)                   │    │
│   └─────────────────────────────────┘    │
└──────────────────────────────────────────┘

┌──────────────────────────────────────────┐
│      Android App (Kotlin/Compose)        │
│   ┌─────────────────────────────────┐    │
│   │  Compose UI + Navigation        │    │
│   │  Platform-specific features     │    │
│   └──────────┬──────────────────────┘    │
│              │  uses (directly)           │
│   ┌──────────▼──────────────────────┐    │
│   │  Shared KMP Module (Kotlin)     │    │
│   │  (same code as iOS shared)      │    │
│   └─────────────────────────────────┘    │
└──────────────────────────────────────────┘

The key architectural principle: UI and platform-specific code live in platform modules. Everything else goes in the shared module.

What to Share (and What Not To)

LayerShare?Notes
Data models✅ YesDTOs, domain models, enums — always share
Networking (API calls)✅ YesKtor handles HTTP cross-platform
Business logic✅ YesValidation, calculations, state machines
Local database✅ YesSQLDelight generates type-safe queries for both platforms
DI / Service locator✅ YesKoin works cross-platform
Analytics events✅ YesEvent definitions shared, platform sends to SDK
UI / Views⚠️ OptionalCompose Multiplatform (beta on iOS) or native per platform
Navigation⚠️ OptionalDecompose/Voyager for shared, or platform native
Platform APIs❌ NoCamera, Bluetooth, NFC — platform-specific with expect/actual
UI framework features❌ NoWidgets, Live Activities, Wear OS — fully platform-specific

Expect / Actual Pattern

KMP's expect/actual mechanism handles platform differences. Declare an expected interface in common code, provide actual implementations per platform:

// Common (shared) code
expect class SecureStorage {
    fun saveToken(key: String, value: String)
    fun getToken(key: String): String?
    fun deleteToken(key: String)
}

// iOS implementation (actual)
actual class SecureStorage {
    actual fun saveToken(key: String, value: String) {
        // Uses iOS Keychain
        KeychainWrapper.standard.set(value, forKey: key)
    }
    actual fun getToken(key: String): String? {
        return KeychainWrapper.standard.string(forKey: key)
    }
    actual fun deleteToken(key: String) {
        KeychainWrapper.standard.removeObject(forKey: key)
    }
}

// Android implementation (actual)
actual class SecureStorage(private val context: Context) {
    private val prefs = EncryptedSharedPreferences.create(/*...*/)
    actual fun saveToken(key: String, value: String) {
        prefs.edit().putString(key, value).apply()
    }
    actual fun getToken(key: String): String? {
        return prefs.getString(key, null)
    }
    actual fun deleteToken(key: String) {
        prefs.edit().remove(key).apply()
    }
}

Common use cases for expect/actual: secure storage, file I/O, date/time formatting, device info, biometric auth, logging, analytics SDK calls.

KMP Library Ecosystem

CategoryLibraryDescription
NetworkingKtorHTTP client with serialization, auth, logging. Works on all platforms.
Serializationkotlinx.serializationJSON/CBOR/Protobuf serialization. Compiler plugin, no reflection.
DatabaseSQLDelightType-safe SQL queries. Generates Kotlin from SQL files. iOS/Android/Desktop.
Coroutineskotlinx.coroutinesAsync/await, Flow. Works across all KMP targets.
DIKoinLightweight dependency injection. KMP support is first-class.
Date/Timekotlinx-datetimeCross-platform date/time handling.
Settings/Prefsmultiplatform-settingsKey-value storage abstraction.
NavigationDecompose / VoyagerShared navigation graph with platform renderers.
Image LoadingCoil 3Image loading for Compose Multiplatform.

Compose Multiplatform

Compose Multiplatform extends Jetpack Compose to iOS, desktop, and web. Instead of writing native UI per platform, you write Compose once:

  • Android: Standard Jetpack Compose — fully mature, Google-backed
  • iOS: Beta status in 2026 — renders via Skiko (Skia), good performance, growing adoption
  • Desktop: Stable — JVM-based, Swing/AWT integration
  • Web: Alpha — Kotlin/Wasm or Kotlin/JS targets

When to use Compose Multiplatform: When you prefer maximum code sharing over platform-native UI fidelity. Good for internal tools, dashboards, and apps where custom branding matters more than following platform design guidelines.

When to keep native UI: Consumer-facing enterprise apps where iOS users expect iOS patterns and Android users expect Material Design. Healthcare, finance, and regulated industries where platform conventions build user trust.

For framework comparison including Compose Multiplatform, see our React Native vs Flutter vs KMP guide.

Migration Strategy

KMP's biggest advantage is incremental adoption. You don't rewrite — you migrate module by module:

  1. Phase 1 — Data models (Week 1-2): Move shared DTOs and domain models to KMP. Both apps import the shared module.
  2. Phase 2 — Networking (Week 3-4): Replace platform HTTP clients with Ktor in the shared module. Existing ViewModels/Presenters call shared API client.
  3. Phase 3 — Business logic (Week 5-8): Move validation, calculations, and business rules to shared. This is where the biggest ROI hits.
  4. Phase 4 — Data layer (Week 9-12): Introduce SQLDelight for shared local storage. Migrate caching and offline logic.
  5. Phase 5 — ViewModels (Optional, Week 13+): Share ViewModel logic using shared Kotlin Flows. Keep platform UI consuming these flows.

Our telehealth case study demonstrates this incremental migration approach in a HIPAA-compliant healthcare context.

Enterprise Adoption

Why enterprises are choosing KMP:

  • Risk reduction: Native UI means platform updates never break the UI layer. Shared logic is pure Kotlin with extensive testing.
  • Team structure: iOS and Android developers keep their expertise. Shared module is maintained by either team or a platform team.
  • Performance: Compiles to native binaries — no VM, no interpreter, no bridge. Smallest performance overhead of any cross-platform approach.
  • Incremental adoption: No big-bang rewrite. Add KMP to existing apps module by module. See the native vs cross-platform guide for transition strategies.
  • Server sharing: If your backend is Kotlin (Ktor, Spring Boot), you can share models and validation between server and mobile apps.

Explore our cross-platform development and Android development services.

Frequently Asked Questions

Is KMP production-ready?

Yes. Stable since late 2023, used by Netflix, McDonald's, Cash App, VMware, and many enterprises. Shared logic is mature; Compose Multiplatform iOS is beta.

How much code can I share?

50-70% with native UI (SwiftUI + Compose). 80-95% with Compose Multiplatform for shared UI. Shared code includes models, networking, business logic, and database.

Do iOS developers need to learn Kotlin?

Not necessarily — shared code compiles to an Objective-C framework. iOS devs write SwiftUI normally. But learning Kotlin (easy from Swift) lets them contribute to the shared layer.

Build with Kotlin Multiplatform

Our team builds KMP apps with shared business logic and native-quality UI on both platforms.

Start Your KMP Project