
One developer is currently available to jump onto a project!
KMP Promised Faster Delivery. So Why Is Your iOS Team the Bottleneck?

Every conversation I have with a CTO who's mid-KMP migration follows the same arc. It starts with one codebase, shared business logic, Android and iOS shipping in sync. Then, around sprint four or five, I hear a version of the same sentence: "The Android team is moving fine, but the iOS team is a bit stuck."
This is not a hiring problem, but a structural problem baked into how Kotlin Multiplatform is adopted, and it's one almost nobody addresses before the migration starts.
I've spent years building and advising mobile teams, and as an iOS developer myself, I've talked to a lot of iOS devs about KMP. Almost none of them wanted to move part of their codebase to Kotlin voluntarily. Not because they're behind on technology, but because the ask is genuinely unreasonable if you haven't set the team up properly.
You're telling someone who owns their entire stack, who knows their tools deeply, to suddenly depend on a shared layer written in a language they've never used, maintained by a team they can't always reach, in an IDE they've never opened.
If that sounds like a recipe for a slowdown, that's because it is.
Let’s go through this “problem” and what actually fixes it.
KMP Is Natively an Android-Friendly Technology, and That's a Design Decision, Not a Bug
The shared codebase in a KMP project is written in Kotlin. That's the entire point, it's Kotlin all the way down. For Android developers, this is a continuation of their existing work. Same language, same patterns, same mental model. The commonMain source set feels like home.
For iOS developers, it doesn't.
In traditional native development, both teams are full-stack within their platform. Your iOS developer owns everything: networking, persistence, business logic, UI. They build the feature end-to-end, in Swift, using tools they've spent years mastering. Same for Android. Two parallel teams, two complete stacks, shipping independently.
KMP changes that contract fundamentally. The data layer, the domain models, the business logic, move into a shared Kotlin module. iOS developers are left primarily responsible for the UI. They go from owning the whole product on their platform to consuming a framework built by someone else, in a language they don't know, with architectural decisions they had no part in making.
.webp)
Sharing business logic is precisely the point, it's why KMP delivers real efficiency gains when adopted well. But the industry talks about KMP adoption almost entirely from the Android perspective, because for Android developers, the transition is nearly frictionless. The Kotlin stays. The patterns stay. The tools stay.
The iOS side of that equation rarely gets the same attention. And that imbalance is where migrations quietly break down.
Usage data backs this up: KMP adoption jumped from roughly 7% to 18% of development teams between 2024 and 2025.
If you're evaluating whether KMP is the right move for your product, check our Kotlin Multiplatform development services.
Where iOS Teams Get Stuck?
When I say the iOS team gets stuck, I don't mean they're confused or resistant. I mean there are specific, predictable failure points in how KMP teams are usually structured. Understanding them is the first step to fixing them.
The dependency chain that kills parallel work
A well-structured KMP project centralizes significant logic in the shared module: networking via Ktor, persistence via SQLDelight or Room, domain models, repositories, and often ViewModels. The iOS developer's job is to consume that shared framework and build the platform UI on top of it.
The problem is sequencing. The shared layer has to exist (and be stable) before iOS developers can build against it. In practice, Android developers build and evolve the shared layer because it's their natural domain. iOS developers wait for the API surface they need to be ready.
Imagine a feature that requires a local caching layer for a user's feed. The Android developer implements the repository in commonMain using SQLDelight. Until that's done and exposed properly, the iOS developer can't build the screen that needs it. If that Android developer is pulled onto something else mid-sprint, which happens constantly in real teams, the iOS developer is sitting idle or building against a local mock they'll have to throw away later.
That's not parallel development. That's a sequential handoff with extra steps.

The "black box" problem: shared code as territory that belongs to someone else
iOS developers encounter the shared layer as a compiled .xcframework or, historically, as an Objective-C bridge header. Neither gives them a clear window into what's happening inside. When something breaks on iOS and the root cause is in shared code, the iOS developer either escalates to the Android team or spends hours debugging something they have no context for.
Tools like Skie (the Swift Kotlin Interface Enhancer) meaningfully improve the consumption experience. Kotlin suspend functions become Swift async/await. Kotlin Flows become AsyncSequence. Sealed classes become proper exhaustive Swift enums. Instead of wrestling with Objective-C-generated headers, iOS developers get an API surface that feels close to native Swift.
Swift Export, shipping experimentally in Kotlin 2.x, goes further, compiling Kotlin directly to Swift rather than routing through Objective-C. The direction is clear and it's the right one.
But here's the distinction that matters for your team: these tools reduce the cost of consuming shared code. They don't solve the contribution problem. An iOS developer can open a commonMain file and still have no idea what to do with it. The fear of breaking Android by modifying shared Kotlin code doesn't go away because the Swift API surface looks nicer.
Tooling context collapse
iOS developers live in Xcode. KMP development lives in Android Studio or IntelliJ IDEA. To read the shared layer, an iOS developer needs a second IDE they've never opened, a build system (Gradle) they've never configured, and a Kotlin DSL in build.gradle.kts that looks nothing like anything in their existing workflow.
The expect/actual declaration pattern is powerful, but it requires understanding a source set structure: commonMain, iosMain, androidMain , which has no direct equivalent in Xcode project organization. Even experienced iOS developers who are genuinely willing to learn hit this wall and slow down significantly.
KMP Was Supposed to Be Faster. So Why Isn't It?
Here's the promise that sells KMP to decision-makers: write the business logic once, ship it to both platforms, let your teams focus on what's platform-specific. One source of truth. Half the bugs. Faster features.
That promise is real: when the migration is done right, the efficiency gains are well-documented. Stone's 130-person mobile team hit 61% code sharing and cut new feature time by roughly 40%. Google Docs runs KMP in production on iOS with performance on par or better than the native implementation. Forbes shares over 80% of code between platforms.
But those outcomes assume both teams are functioning participants in the shared codebase. When the iOS team can't contribute to or confidently reason about the shared layer, the efficiency math inverts.
You're not getting half the work. You're getting Android developers who are productive and iOS developers who are blocked, building against mocks, or waiting. The Android team becomes the bottleneck for iOS delivery, not because Android developers are slow, but because they're the only ones who can touch the code that iOS depends on.
This is also why large enterprises hesitate. A company with mature iOS and Android teams, built over a decade, understands its risk surface. They see KMP's promise, but they also see that they have no model for retraining 15 iOS engineers to work comfortably alongside a Kotlin shared layer without disrupting the delivery schedule they're contractually obligated to hit. So they wait, or they run a small pilot that never scales.
Added the hiring reality: iOS devs who know KMP are rare enough that the job market doesn't reliably produce them, which is why many decide to outsource Kotlin Multiplatform developers, but that leads to another concern: who are the reliable ones?
If you're at that stage where evaluating whether migration makes sense and what it actually costs your team, maybe this blog will help: Adding KMP to an Existing Native App
Enabling iOS Developers to Work with Kotlin Multiplatform
The fix isn't to slow down the Android team. It isn't to force iOS developers through a Kotlin bootcamp before the migration starts. And it isn't to delay KMP adoption until the tooling matures further, the tooling is already strong enough.
We know this because we went through it ourselves. We have iOS developers on our team at Aetherius who work with Kotlin Multiplatform. Getting there required building the process described below from scratch, without a template to follow, and learning which shortcuts cause problems two months later.
Shared-layer contracts as a team practice
The shared module should have a documented, stable API surface, not an internal convention that only Android developers understand by absorption.
One practice that works consistently: introduce an iOS developer review step for any shared API before it's finalized. The iOS developer doesn't write the Kotlin. But they sign off on whether the exposed API makes sense from a Swift consumption perspective, whether the naming is clear, whether the types map cleanly, and whether the abstraction matches how the iOS UI will actually use it.
This forces Android developers to think about the contract, not just the implementation. It brings iOS developers into the design conversation early, and it catches integration problems weeks before they surface as bugs, rather than the day before a release.
Making Kotlin coroutines and sealed hierarchies feel native to Swift is the baseline that makes the shared layer approachable rather than foreign. Without it, iOS developers are fighting the API surface before they've even started building.
Progressive contribution
The goal is not to turn iOS developers into Kotlin developers. That framing sets the wrong expectation and creates resistance before anyone has written a line of code.
The right framing: iOS developers should be able to contribute to the shared layer in the areas they understand, without waiting for Android developers to do it for them.
In practice, the progression moves in three distinct phases.
In the first month, iOS developers pair with Android developers to read commonMain code for features they're actively building, no writing yet, just building familiarity with the patterns, the module structure, and the architectural decisions already made.
By month two or three, they're adding simple data models and extending existing repositories in areas they know well, with Android developers reviewing the output.
By months four to six, they're opening pull requests against the shared layer independently.

At that point, the dependency chain is broken. An iOS developer who can add a data class to commonMain, fix a missing field in a domain model, or extend a repository for a feature they're building, that's the unlock. They're not Kotlin developers, but mobile developers who can move across the full KMP stack when the feature requires it. That distinction matters for how you frame the transition internally, especially with iOS developers who are already skeptical.
It also matters when you're deciding how to staff the project. Building this capability internally takes six to nine months of investment, which is the right answer if you're planning to run KMP long-term with your own team. But if you're mid-migration and blocked now, or if your iOS developers have made it clear they're not interested in learning Kotlin, waiting for internal capability to develop isn't a viable option.
Bringing in iOS developers who already work with KMP gets the migration moving without asking your current team to become something they don't want to be. That's exactly what our team augmentation model is designed for: experienced developers who plug into your workflow within days, not months.
The KMP tech lead role
The fastest path to a functional mixed KMP team is someone who has already done this migration, knows both platforms deeply, and can make the foundational decisions before the team has a chance to make the wrong ones.
Their job is not to write the shared layer and hand it over. It's to set up the architecture before anyone else touches it: module structure, Gradle configuration, expect/actual conventions, the patterns that will govern how both teams work for the next two years, and then stay embedded through real project work, coaching in the context of actual features rather than training exercises.
The distinction between this and hiring a KMP consultant is important: a consultant delivers a shared layer and leaves. The team inherits code they didn't build and patterns they don't fully understand, and every architectural question that comes up after that becomes a blind spot. A KMP tech lead transfers the capability. The team comes out the other end able to make decisions independently, because they made decisions with guidance along the way.
This is the engagement model we run at Aetherius, and it's directly informed by having gone through the iOS-side challenges ourselves. I know what it feels like for an iOS developer to open Android Studio for the first time and try to find where the business logic lives. We've built the ramp that makes that less disorienting, because we had to build it for our own team first.
Making the transition safe
For enterprises specifically, the transition needs a risk model alongside the technical plan.
Start the KMP migration on a bounded feature area, not a full app rewrite. The scope should be meaningful enough that developers encounter real architectural decisions, but isolated enough that a mistake doesn't affect production or slip a release. Define clear ownership boundaries upfront: which parts of the shared layer each team owns, what requires cross-team review, and what can be modified independently.
The fastest way to internalize the shared layer is to work on it during a real feature, with someone experienced available to answer questions in context. Standalone Kotlin training courses almost never produce the same outcome, developers learn the language in the abstract and then still don't know how to navigate the project when they sit down to build something.
Measure the right things. Don't track "how much Kotlin does the iOS team know." Track feature cycle time across both platforms, the ratio of iOS-blocked tickets to Android-blocked tickets, and how often cross-team dependencies surface in sprint retrospectives. Those numbers tell you whether the transition is working far more accurately than any skills assessment.
Case perspective: what a healthy KMP team looks like
After a well-executed six-to-nine month transition, the day-to-day looks different from what most teams start with.
An iOS developer picks up a feature. They open the shared module, find the repository they need, see it's missing a field the new screen requires. They add it in commonMain, write a unit test, and push a PR. The Android developer reviews it, confirms it doesn't break anything on their side, and approves it. Both developers continue building their platform UIs in parallel, without either one waiting on the other.
That's not a heroic scenario. That's what KMP is supposed to feel like when the team transition has been handled properly. The iOS developer isn't a Kotlin expert, they still defer to the Android team on deeper architectural decisions in the shared layer. But they're not blocked. They're not building against mocks they'll throw away. They're not opening a ticket and waiting three days for someone else to add a field to a data class.
The feature ships on both platforms at the same time. Which was the promise.
If your team is somewhere in the middle of this, past the enthusiasm of the initial KMP decision but not yet at the parallel delivery you expected, it's worth a conversation about where the structure is breaking down.
The Tools That Make the iOS Side Less Painful
The tooling picture for iOS developers working with KMP has improved significantly and continues to improve rapidly.
Skie, maintained by Touchlab, is the practical immediate upgrade for any KMP project targeting iOS. As a Gradle plugin with no Swift-side dependencies, it hooks into the KMP build pipeline and produces Swift-idiomatic output: async/await for suspend functions, AsyncSequence for Kotlin Flows, exhaustive enums for sealed classes. Android developers' first reaction to seeing the Swift output Skie generates is usually something like "wait, it actually looks like Swift now." That matters for iOS team buy-in.
Swift Export is the JetBrains-native answer: Kotlin compiling directly to Swift, bypassing the Objective-C bridge entirely. Kotlin types like optionals, generics, and default parameters will eventually map cleanly to their Swift equivalents without the current workarounds.
Both tools reduce friction at the consumption layer. They make the shared layer feel more native to iOS developers who are consuming it. What they don't do, and aren't designed to do, is solve the contribution problem or the team structure problem.
Skie doesn't help an iOS developer understand what to change in commonMain when a feature requires it. Swift Export doesn't prevent the dependency chain that blocks iOS developers when the shared layer isn't ready.
The tools and the team transition work together. One without the other leaves something significant on the table.
Conclusion
The companies getting KMP right aren't the ones with the most sophisticated Gradle setup. They're the ones who took the iOS team seriously as a first-class participant in the shared codebase from the beginning of the migration: not an afterthought, not a team to be "trained later," not a group of developers who just need to accept that their role has changed.
iOS developers who know Kotlin Multiplatform well enough to contribute to it,(who can read shared Kotlin, navigate the module structure, open a PR with confidence) are genuinely rare. Most teams don't have them. Most hiring searches don't find them. Building that capability internally is worth it when you have the runway; when you don't, the faster path is working with developers who already have it.
When your team doesn't have that capability, and the migration is already in motion, you get a faster Android team and a blocked iOS team, which is a more expensive version of what you had before.
The technology is ready. The iOS-side capacity is the last piece. If that's the gap you're looking at, we've spent a lot of time in exactly that problem, and we have the iOS developers to show for it.
to Build Your App?




