back

( Session )

Kotlin Everywhere: KMP, Ktor, and ML in a Real Production App

#Advanced·Session·10:30 am - 11:10 am·Room A
session

Most Android developers draw a hard line at the edge of the app. The backend is "someone else's problem" . Node.js, Python, whatever the backend team uses. But what if that line didn't have to exist? This session is a case study of Affirmi, a production wellness app built entirely in Kotlin , from a Kotlin Multiplatform client targeting Android, iOS, Web, and macOS, to a Ktor backend that handles AI orchestration, machine learning, push notifications, and subscription management. I'll walk through the real architecture, the real tradeoffs, and the real problems that came up — not a toy example, but a shipped product. What we'll cover: 1. The Full-Stack Kotlin Architecture How KMP shares business logic, domain models, and networking across four platforms without compromise. What belongs in shared code, what doesn't, and how the Ktor backend became the intelligence layer the client simply calls. 2. AI Orchestration on the Server Why the LLM should never freely decide what content a user gets. Affirmi's backend uses a spec-first generation pipeline: a scoring function determines the affirmation's tone, theme, and emphasis based on the user's emotional profile — the LLM just renders it. I'll show the actual PromptBuilder, AffirmationSpec, and RankingService code. 3. The ML Personalization Loop Affirmi learns what each user responds to. I'll walk through the full feedback loop: how interaction events (likes, skips, plays) flow from the client to Firestore, get transformed into training samples, and feed a per-user affinity model that changes what the next affirmation looks like. No ML framework required — just smart data engineering and a well-designed scoring function. 4. Server-Side Push Notifications with Ktor Daily personalized affirmations are pushed at the user's chosen time via a coroutine-based scheduler running inside the Ktor process. No Cloud Scheduler. No Firebase Functions. No TypeScript. I'll show the NotificationScheduler, the idempotency design, FCM fan-out, and stale token handling — all in Kotlin. 5. RevenueCat on a KMP + Ktor Stack How to integrate RevenueCat subscription management across Android and iOS from shared KMP code, why you should never hardcode prices in your UI (and what happens when you do), and how the backend validates entitlements without duplicating logic. The honest part: I'll also talk about what went wrong — the architecture iterations, the over-engineering temptations, the phases where the agent-assisted development added complexity faster than it added value, and what I'd do differently if starting today.