Industry: Rides, Food, Shops, Delivery & Payments
JetBrains products used: Kotlin Multiplatform
Careem ↗ is a vehicle-for-hire company based in Dubai, with operations in over 100 cities in 15 countries in the Middle East, Africa, and South Asia.
Careem’s Captain app is an essential tool for Careem Captains – the people who work with the company. They use it daily to earn their livelihood, being offered jobs to pick up and drop off customers in certain areas, pick up food for food deliveries, and more.
We began our Kotlin Multiplatform journey at Careem 3 years ago with the decision to rewrite the engine and infrastructure behind the Captain app on Android. After many hacks over time, it was time to rewrite it and fix many of the architectural issues with the existing implementation. We settled on Kotlin as a great choice for mobile development.
Around the same time, the company decided that we should build an iOS version of the Captain app. Given that we were already rewriting the business logic for Android, we thought, "why not try out Kotlin Multiplatform and create a cross-platform app?" We sold it as a win-win situation – if it works out, we save a lot of time on delivering the iOS app. If it doesn't, we have a clean code base that the iOS team can use as a reference to write equivalent iOS code in Swift.
The experiment was a resounding success! Seeing the cross-platform code in production in iOS increased our trust in Kotlin Multiplatform and allowed our teams to explore sharing more logic. Today, we share libraries that talk to certain backend services across iOS and Android for several of our apps. In other teams, we're using KMM to share event tracking, to solve the problem of making sure events on iOS and Android are reported in the exact same way with the same parameters and event names. Other teams are exploring sharing presentation logic, so that everything except UI logic is shared using KMM. In general, we consider everything except platform-specific UI code, which we prefer to keep native, to be cross-platform and shared via Kotlin Multiplatform.
Most of our cross-platform logic is shipped in the form of libraries that are consumed by our apps. These libraries live in various repositories and are deployed to a Maven repository when they are tagged and versioned for release. This makes it easy for iOS and Android apps to consume these libraries, and it allows modules to be used in the same way as third-party libraries are used.
With time and experience, we've come to rely heavily on unit tests to make sure things work as expected. We've shifted from a mindset of "it works on Android, it should hopefully work on iOS" to a mindset of "if I can make it work on iOS, it'll work on Android." The arrival of coroutines with multithreading and libraries like Reactive make multithreading easier than it used to be.
One thing we learned is that pushing Kotlin Multiplatform in a company requires finesse and care. When iOS engineers hear about Kotlin Multiplatform, their first reaction is often distrust, similar to how many Android developers first react to other frameworks like React Native or Flutter. To get around this, three things help:
- Explain how things work under the hood so developers know the underlying code is native.
- Share the success stories of other companies that use a cross-platform app development approach, and especially talks by iOS developers who have adopted it and benefited from learning an app language such as Kotlin.
- Do not force your iOS team to learn app languages. Instead, start with small pieces that the iOS team will agree to try out. One good example of this is business logic for a new feature that needs to be built; sharing analytics is another.
With time, we've found that our iOS teams, who initially did not trust cross-platform mobile development in general and Kotlin Multiplatform in particular, became teams that were recommending it for pieces of tricky logic and were comfortable learning Kotlin (especially given its similarity to Swift) and contributing substantially to the code as well. Using Kotlin for cross-platform mobile development, we were able to share code and deploy the iOS Captain app in much less time than we would have otherwise.