At Ricardo, we have two perfectly fine apps, one for Android and one for iOS. They look and feel quite similar. But more importantly, they should behave exactly the same. One of the challenges that we have, is that each topic team only has two mobile developers, one Android developer and one iOS developer. Features they implemented natively might have started off similar, but as time progresses they can look quite different in terms of business logic. On one platform a change can be introduced that is not added on the other platform for example. This can lead to more bugs and unexpected behaviour of our apps. Moreover, if two features should behave the same, why are they implemented twice, in the same way? To solve this problem, we started to use Kotlin Multiplatform.
In this article, I will walk you through our experience – from early proof-of-concepts to full-fledged implementation – highlighting the challenges we faced, the solutions we found, and our vision for the future of KMP at Ricardo.
So What is Kotlin Multiplatform (KMP)?
KMP is a technology that allows developers to write code once for various platforms but it retains all the benefits of native programming. The code can be shared easily for iOS, Android, macOS, Windows, Linux and even Web! At Ricardo, though, our focus is exclusively on iOS and Android.
Unlike fully cross-platform frameworks like Flutter or React Native, KMP focuses on sharing logic, allowing each platform to retain its native UI and feel. You can share as little or as much as you want, and you can add it immediately to your existing code base. Preventing a full rewrite of your apps, and preventing a full lock-in to the technology. Additionally to that, as it’s fully written in Kotlin, Android developers don’t need to learn a new language and for iOS engineers it’s easy to pick up since the language semantics are quite similar to Swift, which is used in iOS.
How Did We Implement It at Ricardo?
We made several proof of concepts to make sure KMP would really help us, and to address all the concerns of our mobile guild members. For Android developers, it wasn’t a significant change, but for our iOS engineers, adopting a completely new technology was a bigger adjustment. As it’s important that every developer is on the same page, we wanted to address all of the concerns regarding tooling, way of working or more in-depth concerns, for example regarding threading.
Additionally, because both of our apps have grown apart, it was also needed to align our vision of the target architecture. Without this, it would have been almost impossible to integrate our shared code properly.
Once all of the blockers were resolved, we could move on to an implementation phase. We had the initial goal of just migrating our network/data layer of the apps to KMP but since everything went so smoothly, we even started moving business logic already to KMP, way ahead of our initial plan!
Some Technical Details in a Nutshell
For now, we only share code up to the view layer. From our shared code, we only expose “interactors” (an interactor is a part of clean architecture that handles the core business logic, connecting the pieces to process input and deliver the right output). All of the other components are marked as “internal” and can’t be accessed by the consumers of the shared code. Our interactors often expose some functions or a reactive flow of data, the consumers can listen to this flow of data and update the UI of our apps when the data changes.
All of our exposed functionality return a type of Result, this holds either the success value of the called function or the failure in the form of domain error. This allows us to handle our errors gracefully, and more meaningfully. Our shared code is integrated in our Android project as a Maven dependency and in iOS via CocoaPods.
Where Do We Stand Now and Where Do We Want to Go
At the moment, several key features of our app are leveraging KMP. These include functionalities on the order detail screens, our notification hub, and the product screen, though the latter is not yet fully integrated into iOS. Additionally, a significant portion of our network calls is now shared, streamlining communication across both platforms. In 2024 alone, we had merged over 120 pull requests, with contributions coming from both Android and iOS engineers, showing how actively the entire team is involved.
All of our new features will be using KMP, and where it makes sense, old features will be rewritten using KMP. Rewriting luckily means often just moving code from our Android code base, to our shared code base.
This year, we’re aiming to make the developer experience with KMP even better. It’s already pretty great, but we think it can get even smoother by integrating the shared code directly into the Android and iOS projects. This way, we won’t need to jump between repositories, making it easier and faster to build new features.
KMP has already become super popular in mobile development, and with Google officially backing it, we’re even more confident it’s here to stay. On top of that, Google has started making some of their Android libraries work with KMP, which is a huge win for everyone using it!
Special Thanks!
I would like to give a special mention to our mobile guild members, who have been very supportive in making this transition to KMP happen. Thanks Nicolas, Jessica, Jerome, Ingrid, Yannick, Giovanni, Sergei and Zsolt, you are all awesome!

Author
Ronald van Duren
Senior Mobile Engineer
General Marketplaces