Not-So-Micro-Services - a Commentary on the Shift in System Design Trend
Where we stand
Microservices has been the number one catchphrase on the system design list for quite some time, and for a good reason. We can find everything being micro, from small apps to huge 1000+ component systems yet we often forget that designing and building a microservice system is a very demanding task. Nowadays, when many mistakes in that field have already been made, more and more people begin to realize that being ‘too micro’ might be a bad thing.
Let us first talk a bit about the key selling points of the microservice approach. I think the main advantage is that they force the modularization of the system. Systems have to be split into smaller parts that are easier to design, develop, test and deploy. With modularization comes the ease of scaling the more stressed parts of the system and, if required, resilient integration technologies between the components. When well placed, those integrations can safeguard the whole processing flow from failing in stress points, which increases the overall reliability of the system.
On the other hand, each of the previously mentioned benefits comes at a cost. Even if modularization makes a small part of the system easier to develop, the overall architecture and linking parts of the system together is much more complicated. Scalability requires extra configuration and careful service design to work at all. And resilient integrations add to the overall system complication, execution overhead and required maintenance
A bit about macroservices
Yet none of the previously mentioned, easily noticed disadvantages of the microservice approach seems to be the main reason why people and companies are starting to shift away from it. Gergely Orosz, an Engineering Manager on the Payments Experience Platform at Uber, following up on Cindy Sridharan, a distributed systems engineer, mentioned in April 2020 a new approach that Uber has been moving toward.
They call it ‘macroservices’ or ‘well-sized services’. The idea behind it is that, while the microservice approach helps to quickly develop a good quality system at the beginning, with the system and microservice landscape growth, testing and maintaining the vast number of components can outweigh their benefits from the earlier stages of the system life cycle. Such a phenomenon is easily visible with bigger systems, but happens all the same in smaller ones, especially with smaller teams to support them.
Macroservices are meant to be the middle ground between the hegemony of the monolith and the land of free microservice. Let's consider the possible advantages of this approach.
With a smaller number of components, designing a system could potentially be much easier. It’s not all sunshine and rainbows, of course, demanding being more careful with how the system is split. But with a balance between splitting and merging functionalities into encapsulated services a more future- and the expansion-proof system could be designed.
With fewer components, it’s harder to distribute and parallelize development and that might be a huge no-go for many projects and organizations. It greatly depends on a particular case, but I think that many of the issues with the more difficult development can potentially be mitigated with careful planning and development management.
It is another drawback when compared with the traditional microservice approach. Bigger services are harder to scale. There could be more consistency issues but usually, eventual consistency can be achieved.
Infrastructure and deployment
With a smaller number of components, fewer integrations should be required. Some resiliency components like queues or streams could be used within a service itself, which by complicating a particular service would simplify overall system architecture.
Maintenance and testing
A bigger service is more problematic in terms of maintenance, but a smaller number of services requires less maintenance work overall. The same goes for testing. A bigger service requires more thorough internal testing, but a smaller number of services requires less integration testing, which from the pyramid of testing point of view is a good change.
I think the key takeaway is that when choosing macrosercies over microservices it’s possible with careful design and planning to retain many of the benefits of the microservice approach while mitigating most of its drawbacks in later stages of the system life cycle.
The question that arises is: since macroservices aim to be the best of two worlds, will we be able to draw the line somewhere and not fall into the traps of both monoliths and microservices yet again?
Article written by Jakub Słoniec