How we use mitosis to split the monolith
We’ve all been there. The project we’re maintaining is a highly coupled BBOM and all we want to do is to micro-service the hell out of it and split it into smaller bits with single responsibilities.
So how do we go about doing it? There are many articles explaining different techniques. In this particular article, I’d like to describe how we started splitting our own monolith. When planning, we wanted to start with the smallest possible chunk and move it to a separate service while doing so in a very controlled manner. At the same time, we wanted to be very informed about where we stood in the process, in order to increase visibility and to be able to estimate how much work was left to do.
Many years ago I studied biology, and the process of splitting the monolith into multiple services in a controlled and gradual manner tickled my memory and made me go back and read a bit about mitosis. I’ve presented this metaphor to my colleagues and we’ve decided to plan and visualize our process accordingly.
In this article, I’d like to show you what we did.
Our setup is simple and well-known. A UI is making calls to the backend through a restful API. The endpoints include multiple different areas and are implemented using a multi-layered architecture. The data is saved in a relational database.
One of these areas is the back office. It allows admins to set up and maintain basic data for the system users to work with. The back office is such an isolated part of the system that we naturally considered it a great candidate to split into a separate service. It is also small enough and does not contain too much business logic so we thought it would be easy enough to move it.
Obviously, we were wrong. Nothing is ever easy when splitting a monolith. Live with it or find another industry. No free lunches here either.
Anyway, the back office data is composed of multiple fractions, and for the sake of my employer’s integrity, I’ll lie and say they are all about pool equipment: tables, cues, chalks, gloves, etc.
In order to make the changes as small as possible, we decided to take one of these fractions and apply the mitosis process to it. That way, we could evaluate our process and see if we’re doing things right, and repeat with the next fraction if we’re happy with the result.
The following list tries to explain the different parts of the process.
This is the original state, in which there is only one back-end that includes all of the endpoints, business logic, and CRUD operations.
In this phase, we move everything that has to do with the current fraction into a separate module of the monolith: endpoints, business logic, and database queries. This will help us later when moving the module into its own service.
Here, we create a separate service (or if it is the nth time around, use the existing separate service) and move the code from the module into it. We create endpoints in both services to allow them to save and retrieve whatever data is needed. These endpoints correspond to the method calls previously made between the modules.
Note that both services are currently using the same database. But don’t be alarmed, this is only a temporary phase. Also, the UI is still sending requests to the monolith. It is unaware of the ongoing split.
In this phase, we create a new database for the back office service. It contains only whatever needed tables. If we realize that the monolith still requires access to any of them, then we probably didn’t isolate all of the fraction details properly and thus reconsider whether we should move more parts into the new service or create more endpoints to serve the monolith’s needs.
Now it is time to move the relevant endpoints from the monolith into the new service and to redirect the calls from the UI to them. Before removing the endpoints from the monolith, you can verify that everything is working properly by creating the same calls to both services and comparing the responses.
If everything is fine then we celebrate and move on to mitosing the next fraction.
So what’s so great about this approach?
- It creates a well-defined roadmap. You know exactly what you’re supposed to do at every stage.
- Every step is as small and isolated as possible. If you made a mistake, it is not a huge one and it shouldn’t be too painful to recover from.
- It’s predictable. After a few iterations, it can give you an estimate that might not be too far from the truth.
- It’s scalable. With good isolation, multiple teams could possibly work in parallel.
- It gives you a vocabulary to describe your progress. For example, you can say that one team is in the metaphase stage with the cues, while another is in the anaphase stage with the chalks. This also lets you create some beautiful visualizations.
So does it work? Actually, it is a bit too early to tell as we are still in the middle of the process. But we are cautiously optimistic about it.
I hope this metaphor could help you blast your monoliths too. Please comment below if you have any thoughts about the process.
Have fun mitosing!