Modern KMP adoption for native mobile teams - droidcon New York 2024
- By —
- Kevin Galligan
- Date —
- Filed —
- Talks
- Length —
- 47 min watch
AI was used for content on this page Chapter markers and summaries on this page were generated by AI from the video transcript.
The companion talk to the keynote, and a much less cheerful one. The premise: adding some KMP is easy and most teams succeed at it, while scaling KMP is hard and most teams fail. The interesting question is why — and the answer has more to do with workflow and team structure than with tooling.
Chapter links jump into the video.
Framing the problem
- 0:03 — Intro — Most of this content also exists as a long blog series on the Touchlab blog. It was meant to be seven parts and kept growing.
- 1:24 — Season two — This is an ongoing series about how teams actually use KMP. A lot gets cut from this version, because it’s a big topic and most of it isn’t mechanical — it’s people, which is the hard part.
- 2:04 — Credentials — Almost a decade, if you count the J2ObjC work that predates KMP — philosophically the same problem. Room running on iOS in 2017, the day after it launched. All in on KMP in 2018, which was probably not a great idea.
- 3:25 — What we built along the way — The first multiplatform app in the App Store, the first iOS app with Compose, generics in the Objective-C output, Xcode debugger work, SKIE, and an SPM publishing tool.
- 4:05 — The good news and the bad news — KMP is stable, Google endorses it for shared business logic, and plenty of teams are trying it. Adding some KMP is easy and most teams succeed. Scaling KMP is hard and most teams fail.
- 4:47 — Why, not how — The how is in the blogs and videos. What’s missing is an understanding of why the hard parts are hard. These are observations and opinions; the only advantage I have is having done this for a decade.
- 5:30 — There’s no useful team guidance — Most of what exists is respectfully imagined rather than lived. That’s not unique to KMP — all new tech starts there. We’re in the feedback phase now.
- 6:10 — Problem shedding — Picking the concrete problems people talk about, solving those, and never getting to the existential blockers.
- 6:51 — The big issues few discuss — A major workflow mismatch, team structure, real team planning, and the fact that KMP people are overwhelmingly Android people — industry-wide, not just on your team. An experienced iOS developer who genuinely knows KMP is extremely rare.
- 7:32 — The issues everyone discusses — Tooling, Objective-C interop, Gradle setup, the single framework problem. Real problems, actively worked on, and the kind engineers gravitate to because they feel solvable.
- 8:14 — The cycle of hope — “Once we have X, the iOS devs will finally get it.” The strict memory model went away. SKIE exists. Swift export is coming. That is not how it works, and the cycle keeps us from figuring out the real thing.
- 8:58 — “iOS devs are close-minded” — I hear this fairly often, and a lot of them think exactly the same thing about you. Some of their complaints aren’t great. Some are very important.
Scoping it down
- 9:38 — The specific lane — A team of a few mobile devs who are platform specialists, mostly existing apps and teams, mostly multiple repos. General advice isn’t nuanced enough to be useful, so this talk narrows deliberately.
- 10:59 — KMP works — You can absolutely build a large app. Picture a maximal KMP app with native UIs and a lot genuinely shared — the value would be obvious. The problem is that the bigger the team, the fewer examples of it exist.
- 11:40 — We need test subjects — You can’t test big ideas in a lab. Nobody is going to have a group of developers pretend to build an app for two years. Someone has to try this for real.
- 12:22 — Two classic approaches — The default: a monorepo with everything in one place, which is what nearly every sample app looks like. The alternative: the library model, where the KMP repo is external and publishes versioned libraries to both apps.
- 13:43 — All team guidance says “library” — Libraries are familiar, they don’t disturb anyone’s workflow, and adding an Xcode dependency is easy. It’s also hard to argue against.
- 14:23 — What the library phase teaches you — Packaging, Swift-facing APIs, crash reporting, binary size. If you’re an Android dev who writes whatever Kotlin and exports it, the resulting Swift API is often not good. You’re learning here, not proving efficiency.
- 15:06 — Why it’s always the advice — Imagine the first step being “merge your production repos, then we’ll try KMP.” For a double-digit team, good luck. At the start your KMP is a sliver — that’s a dramatic ask for something not everyone is sold on.
- 15:47 — Already in a monorepo? — Add a module, but still treat it like a library. At minimum, don’t let devs change KMP on the fly while making app changes.
Team vision
- 16:28 — Decide what success looks like early — Not “let’s see how it goes in a year.” If this works, what does everything look like?
- 17:08 — If the answer is “just libraries,” you’re done — A few shared modules, or replacing something specific. Google Workspace is essentially this at enormous scale. Libraries are the easy case mechanically and the easy case for people. The rest of the talk is about the other visions.
- 17:48 — Where does your KMP live? — Native is UI, that part is easy. The decision is everything between that and the libraries.
- 18:29 — The real question — Is KMP in your feature code? Are you directly supporting day-to-day app development, or are you writing libraries? Then: who does what? Are iOS devs fully contributing to the KMP, or implementing the iOS-facing parts and making those Swift interfaces less horrible? That’s a decision you make up front, and it can evolve.
- 19:49 — “Everybody does everything” — Some of you think that’s crazy. Some of you think it’s the dream.
Library dev vs. feature dev
- 20:30 — The distinction — Library dev: physically separate, independently developed, slow-changing from the consumer’s side, incrementally versioned. Feature dev: app UI and architecture, edited as a unit, rapid concurrent conflicting changes. That’s what git is for.
- 21:12 — What’s library-shaped — Server calls change on the server’s schedule, not yours. Tax calculation doesn’t change because you’re touching onboarding. Local DB changes involve migrations, so they’re slow and explicitly linearly versioned. Features are none of those things.
- 21:53 — Developed as a unit — You set up the architecture as far as seems appropriate, then build the screen, then change the architecture, because you don’t know everything up front. If your team genuinely doesn’t work that way, I’d like to hear about it — it changes the mental model.
- 23:17 — KMP’s golden rule — If you wouldn’t do it without KMP, maybe don’t do it with KMP. “KMP will force us to write better tests” is not a great reason. Nothing is stopping you from doing that now.
- 23:59 — Where the library-only path lands — You have KMP, you can check the box, and it isn’t doing much. You may have added a couple of megabytes to your iOS binary for four server calls.
- 24:39 — Scaling means going where the action is — More shared, less platform-native. For most native mobile devs the action is feature work. A few modules is a great way to start and a bad place to stop.
The workflow bottleneck
- 26:00 — Feature dev doesn’t work with a library model — It works. It doesn’t scale.
- 26:41 — Git is the bouncer — Feature work is many concurrent conflicting changes in one repo, and that’s fine, because that’s the problem git solves. Library dev has fewer conflicts and, critically, linear versions.
- 27:22 — What the loop actually looks like — Change the KMP, test locally, push the KMP PR, wait for approval, wait for the build, pull latest main because others committed in the meantime, then your app changes, then that PR, then the other app. It’s a lot of process for one feature.
- 28:02 — Linear versions are the problem — With two devs you coordinate on Slack. With twenty it simply does not work.
- 28:42 — The horizontal limit — It caps how much you can share and how many people can work on it at once. KMP’s potential value gets eaten by the workflow bottleneck. Some teams see it coming and try anyway.
- 29:22 — Why this matters beyond your team — Small teams share a lot, big teams share a little. People assign more weight to big names, so when large teams say “we tried it, it didn’t do much,” that becomes the story. Sharing code is KMP’s killer feature — if that doesn’t land, it’s a serious problem.
- 30:02 — When linear versions are fine — While you’re learning and not moving fast. Sorting out architecture, working out where the boundary sits, asking the iOS team what they actually want.
- 30:42 — KMP is your app code — Android devs get this immediately because it’s all Kotlin. For iOS devs it stays “that other thing,” and that framing has to change if it’s in day-to-day feature work.
The monorepo, and what it costs
- 31:24 — Merging solves one problem and creates another — I can’t name a medium-to-large team with an existing app that merged production repos for KMP. But grant it: now changes couple both platforms immediately. An Android change touching KMP hits iOS — maybe positively, maybe not, maybe it crashes.
- 32:05 — Mutual disappointment — I interviewed people doing KMP at larger companies to ask how they mitigate this. They’d joined the call hoping I’d tell them. Mostly the answer was “we just do library.”
- 32:45 — The mitigations on offer — Pair coding across platforms, strict architecture with tests you actually rely on, or making everyone a generalist. All of them affect workflow enough to reduce the value you were chasing. Morale and retention are also real considerations.
- 33:27 — What devs will actually do — Write it natively and hope nobody notices, leaving managers to police where code belongs.
- 34:07 — Breaking the silos is a 15-year-old idea — People have been calling for it since before there were Android phones, and it hasn’t happened. Explain that however you like, but it should give you pause. Specialists exist for a reason — we’d not have cardiologists if we didn’t need them.
- 35:27 — Maybe it’s a cognitive limit — In a complex app it may not be possible to maintain competence on both platforms at the level the work requires. I’m not asserting why. I’m reporting what I observe. And you can try this today without KMP — few do.
- 36:08 — Reduce the risk, take it in stages — I’m not saying you can’t. Don’t assume it’ll be smooth, and definitely don’t assume KMP makes it happen by itself.
- 36:50 — KMP wasn’t designed around native mobile teams — Not a dig at JetBrains. The technical design is elegant and makes sense for what it does. But the monorepo default is deeply embedded, and in season one I didn’t even question it — I just tried to mitigate it.
- 37:30 — It never got stress-tested by a real team — Nobody handed a barely-working version to a hundred mobile engineers and asked how it went in production. That’s the phase we’re in now, and “library or merge everything” isn’t going to carry it.
Two teams that made it work
- 38:11 — Story one — Greenfield, 15-20 devs, hired for this, monorepo from the start. Everyone is expected to learn KMP and most devs work on both platforms. Their order was UI, then view model, then wiring — the inverse of what I expected — plus “heavy-handed guardrails,” which I still want to dig into.
- 39:33 — Story two — Also greenfield, ~20 devs, half and half, everybody does everything. They reached out because the iOS devs were struggling with Kotlin. My question was whether the Kotlin devs were fine with Swift — they weren’t. Kotlin engineers can learn Swift syntax, but thinking in Swift is different, and their PRs consumed the Swift devs’ review time. So the Swift engineers went back to doing all the Swift.
- 40:53 — What both stories have in common — Greenfield app and greenfield team, hired for this, with a lot of bending. Long-term members do eventually become productive on both. These aren’t bad stories — they’re examples of what scaled KMP has cost so far.
- 41:34 — Maybe big existing teams won’t scale KMP — Or maybe I need a different definition of scale. I don’t like thinking it through. The tech works; why is this so hard?
A different plan
- 42:14 — Don’t couple anything — Not the teams, the workflow, or the repos. You’ll talk more and pair on some architecture — of course. But don’t force the teams into lock step all the time, and let specialists be specialists.
- 43:35 — The pitch for iOS devs — A KMP developer with real iOS experience is rare and will be in demand. Tell a good story and create a path for the whole team — “you have to do less work” isn’t one.
- 44:16 — The branching strategy — A KMP repo exists, but the KMP actually lives in both app repos, tracked rather than submoduled. The KMP repo coordinates changes between them; you never edit it directly.
- 44:56 — What that gets you day to day — Devs change app code with their usual process, in their own repo, without worrying about breaking the other platform. Turn off the other source set. CI carries KMP changes across and does the bookkeeping.
- 45:37 — The one explicit step — At some point an iOS dev branches, pulls the accumulated changes in, implements and tests the iOS side, and merges through the normal flow. Decoupled teams, no merged repos, no up-front demand that everyone learn everything.
- 46:18 — It’s a research tool — It won’t scale to a large team as it stands, and it needs feedback. But trying it won’t blow up your workflow — it’s a separate repo, and you can run the whole thing locally on a test branch.