At leboncoin, we’re migrating to a microservices architecture. Here’s why we’re doing it, and what we’ve learned.
Leboncoin, the leading classified ads platform in France and one of the most visited globally, is powered by a classic three-tier architecture. Our business logic tier is one big monolith though. It powers leboncoin.fr website, the iOS and Android applications and all our APIs. It continues to serve us, our users and customers well.
But over time, as a codebase grows in size, so does its complexity. Different parts of the codebase become increasingly tightly coupled with one another (this is referred to as software entropy. You can read more about it in The Pragmatic Programmer book).
This coupling means that changes in one part of the codebase can impact other parts, so they need to be changed in turn – although they are outside the scope of the original feature or fix being made.
Software entropy makes introducing new features slow and complex with a lot of overhead. It also makes it difficult to streamline processes and can cause friction with stakeholders. Refactorings to reduce the technical debt become expensive, complex and time consuming, making them less likely to happen.
Working with such a codebase can really slow you down. To address the challenges of software entropy, ever-growing complexity and the resulting decline in velocity, the backend team at leboncoin has devised a three-part strategy, which will eventually take us to a microservices architecture-based backend.
Part one: Feature Freeze (a.k.a don’t touch it!)
Throwing away the existing codebase is obviously not an option, and rewriting from scratch is a risky endeavor that would bring the introduction of new features to a halt.
Feature freeze basically means that the legacy codebase enters maintenance mode where changes would be limited to bug fixes or otherwise urgent changes, but no new features would be introduced. Maintenance can be a resource hog, but the good news here is that our code base is covered by an extensive regression test suite. These tests are run as a nightly job in our CI environment, alerting us when and if the monolith needs attention. The monolith can rest comfortably while we transition to our target architecture.
Part two: APIs, APIs everywhere
The pun about “rest” in the previous section was intended. As stated above, part of our strategy is to transition our entire backend to a set of RESTful API endpoints implemented in microservices and following a microservices architectural style.
The first step is to create shims over the legacy (non-RESTful) APIs (the blue blocks in the diagram above). Creating a shim in this context is to introduce a new API only using the existing software. In other words, we are not going to write new code for functionalities already provided by the legacy monolith, but introduce “old new” APIs based on existing code. Once all of our clients have migrated to these new APIs, we are free to rewrite the underlying code as we see fit without putting current developments at risk or delaying new features. This work is already underway, with components like authentication and user accounts management in production.
Part three: Code, Ship, Repeat using API Gateways
The third stage of our strategy is to create microservices to implement new RESTful APIs for our clients to ship new features from now on. The new APIs would be implemented by cohesive microservices containing a small number of strongly related API endpoints.
To support this microservice-based architecture, we have introduced a new piece of infrastructure: an API Gateway. Using an API gateway lowers the barrier to enabling a new microservice in production. The team or developer responsible for a microservice just needs to deploy it and configure the API gateway to route incoming requests to it. And voilà, the microservice is up and running in production, ready to process requests.
The API Gateway is a first step in broader plan we are laying down to build an infrastructure that supports our migration to a microservices architecture … but that would be a topic for another post!
These are really exciting times to be a software engineer at leboncoin. There is lots going on, on many fronts and not only on the backend side. So if you enjoy taking on interesting technical challenges, working with cool new technologies (did I mention that we have switched to golang as a primary programming language?), we are looking for talented software engineers to join us.