Monoliths in a World of Microservices

By Madalin Stefircă

You may find yourself tomorrow in the enviable position of having to decide the path for a project’s architecture. We all know that nowadays microservices are popular. However, we also understand that we can’t move everything to microservices just because it is cool. Being able to brag to your friends about working on such a project doesn’t count.

I started my career working on projects following a monolithic architecture, but when the microservice hype wave started, I kept an open eye.  Being a bit conservative, allowed me to focus on the things I knew best, but at the same time, I felt the responsibility to learn as much as I could about microservices architecture, so that I could potentially answer the question “why not switch to microservices?”.

Luckily, it didn’t take long for me to gather firsthand experience on the eternal question of monoliths vs. microservices – some success stories and some failures. One noteworthy example was a large-scale project, structured as a monolith and run by a team who were keen on migrating to a microservice architecture. Only thing was, the project itself was not really suited for such a drastic change and would have greatly benefited from pursuing its original structure. Nonetheless, the change was performed, which in turn made the developers’ lives a nightmare – their straightforward solution became a complex, unstable, error-prone one with limited options of improvement. Looking back, I realize this story could be construed as a bashing of microservices, but that is not the case – this was nothing else but a series of unfortunate decisions.

However, the experience itself helped me cement the idea that there is no universal solution in architecture. Soon after that, I found myself in charge of a monolith project that had some large-scale planned changes. With the need to rethink most of the business model, I analyzed the opportunity for some serious restructuring.

What was initially a small, straight-forward application, guiding medical center customers through a flow, now had to support a completely new flow, with new concepts and access levels, bringing an increased level of complexity. After some analysis of the new business requirements, I decided to split the platform into modules, to allow flexibility and enable additional modules to be added later. These modules would also have common functionality so this meant extra care in splitting and structuring. The idea was taking shape in my head, but I needed to make the research to support it and make it come alive in a professional manner.

This was it! – the opportunity to start asking the big questions: “Should we migrate to microservices?”, “How would we migrate towards microservices?” “Are we ready for this?”.

So, let’s roll up our sleeves and get dirty

Arriving at the first question, “Should we migrate to microservices?”, the answer was: “I have my doubts”. The clients clearly wanted scalability, and the project promised to increase in complexity, so managing it with microservices would have made sense. On the other hand, based on the history we had with this client, we knew that they had limited budgets assigned for software development and they always have been rather reserved on increasing costs for resources and other services. Small teams and lower budgets don’t usually go well with microservices. Also, the platform was growing, but at that point it was not expected to expand across several tenants or different regions, as the usage was limited only to one company inside a single country. In conclusion, my answer to this question was yes and no. Great!

I still needed to at least go on with my investigation, in hope that an answer to “How would we migrate towards microservices?” would bring up more hints. I started thinking about architectural layering and slicing.

As you may know, in software architecture, a layered architecture is a design approach in which the functionality of an application is divided into layers, with each one serving a specific purpose and communicating with the layers above and below it. A horizontal slice refers to a section of an application that cuts across multiple layers, typically comprising components from the presentation, business, and data access layers.

In our architecture, we already had horizontal slicing in place, so the next step would be to look at vertical slicing.

Vertical slicing refers to the organization of the codebase into stacked layers, with each one having a specific, well-defined purpose, communicating with the adjacent layer. Each layer depends on the ones below it and provides services to the ones above it.

Vertical slicing is often used to design software systems that are easy to maintain and extend, as each layer can be modified and updated independently of the others. It also helps to enforce separation of concerns, as each layer is responsible for a specific set of tasks and does not need to worry about the implementation details of other layers.

This would work with us splitting into different modules per business flow. And the result would be a combination of the two:

It seemed as though we could proceed with some architectural restructuring to obtain microservices out of them. And now the last question remained: “Are we ready for this?”. Pondering upon the question, I realized that to achieve anything big and important, things need to go slowly and in well-organized steps. So, a plan that would make sense for the migration would look something like this:

We can notice that there are several steps that keep the application in the monolithic architectural area, but the structure would morph into bits that would then allow for easy picking and splitting into microservices when ready and needed.

Conclusion

Having all this data in place, my conclusion was that the migration could take place, but in steps, moving towards a microservice-oriented architecture, this being the wisest and safest decision for now.

Most of the analysis done showed that the project was not ready for a total migration, but that did not mean it should prevent us in organizing the codebase in a hybrid, modular monolith, slowly taking the steps towards our goal, and making the required steps only when the team feels mature enough and/or the platform actually grows to the point where the migration is a must.

This way, the evolution of the code gets to be organic, progressing in time in the direction we want it to, benefiting of the elegance and isolation that the inner modularity provides, while keeping it a monolith to serve its purpose under the current circumstances.

About Madalin Stefircă

Madalin wears many hats in our team. He is both a Senior Expert Software Developer, as well as a Team Lead and Tech Lead. His focus, both in his work and his interactions within the team, is on self-improvement through continuous learning, and using the newly found knowledge to understand problems and applying it to the right scenarios, always with an open mind.

 

Share this article