My First Step Into System Design as an Android & Kotlin Multiplatform Developer
I have been working mostly around Android and Kotlin, and more recently I've been spending a lot of time learning Kotlin Multiplatform (KMP) and Compose Multiplatform (CMP).
For a long time, whenever I heard System Design, I thought about things like:
- How do we handle millions of users?
- How do we scale a database?
- Do we need Kafka?
- Should we use microservices?
- How do we design something like YouTube or WhatsApp?
So, honestly, System Design felt like something that was mainly for backend engineers or very large systems.
I was wrong.
The more I started learning about it, the more I realized that I was already making System Design decisions in the applications I was building.
I just wasn't calling them System Design.
My Initial Way of Thinking
As an Android developer, I used to think a lot about things like:
- Where should this class go?
- Should this be in data?
- Should I create an interface here?
- Should I use a repository?
- Should this code be shared in KMP?
Those questions are useful.
But I started realizing that there is a better question behind them:
Why?
- Why should this class belong to the data layer?
- Why does this interface exist?
- Why should this code be shared?
- Why should one part of the application know about another part?
That "why" is what started getting me interested in System Design.
Then I Started Looking at Architecture Differently
One of the first things I explored was layered architecture.
Usually, we see something like:
Presentation
↓
Domain
↓
Data
It looks simple.
The UI is in one layer, business logic somewhere else, and data access somewhere else.
Initially, I thought this meant that if I changed something in one layer, I shouldn't have to change anything in another layer.
But then I realized that's not really what layered architecture guarantees.
It gives us separation of responsibilities.
It doesn't automatically guarantee that changes will stay inside one layer.
That was a small realization, but it changed the way I started looking at architecture.
Then Came the Model Confusion
Another thing that confused me was models.
Suppose I have an API for orders.
- The API gives me an
OrderModel. - The business logic needs order information.
- The UI also needs order information.
So should I just use the same OrderModel everywhere?
At first, that seemed completely reasonable to me.
Why create three different models when the data is basically the same?
But then I started understanding that data can look the same while having different responsibilities.
- An API response model exists because of the API.
- A domain model exists because of the business.
- A UI model exists because of what the UI needs.
They might contain similar fields. They might even look almost identical. But that doesn't necessarily mean they should be the same object.
This was one of those things that sounded like over-engineering to me initially. Now I understand why the distinction can matter.
And This Is Where System Design Became Interesting
I started noticing that most of my questions weren't really about syntax. They were about boundaries:
- Who should know about whom?
- Who should own a rule?
- Where should an abstraction live?
- What happens if something changes?
- What happens if I have two implementations of the same interface?
- What should be shared between Android and iOS in a Kotlin Multiplatform project?
- What should stay platform-specific?
These are System Design questions.
And they exist even if your application isn't handling millions of users.
Why I'm Writing About This
I'm still learning.
I'm not writing this series as someone who has all the answers. I'm writing it because I want to document how my understanding changes as I learn more.
I'm Ankit, an Android and Kotlin Multiplatform developer, and most of my experience has been around Kotlin, Android, KMP, and now Compose Multiplatform.
So I'll be looking at System Design from that perspective.
I'll probably get confused about things. I'll probably change my opinion about some patterns. And that's okay.
I'd rather understand why something works than simply memorize that "this is the recommended architecture."
That's what I want this series to be about.
What's Next?
In the next posts, I want to go deeper into the things that initially confused me:
- What exactly does Layered Architecture give us?
- Where should models actually live? (Domain vs Data vs Presentation)
- Why do we need interfaces?
- What happens when multiple repositories implement the same interface?
- What does Dependency Inversion actually mean?
- When does abstraction help, and when does it just add complexity?
- How do these ideas apply to Kotlin Multiplatform?
I'm going to figure these out one by one.
And I'll write about what I learn.
Let's see where this goes.
