A Decade Later: Microservices After the Hype
A few years ago I wrote a blog post titled “My take on microservices”. I cannot believe it has been almost a decade, nine years to be precise, since I published it. It is still accessible on my old blog via this link if you want to read it.
My view on microservices has not changed that much from a technical or architectural perspective. The principles I laid out in that article are principles I still follow today when designing or migrating systems to microservices based architectures. I genuinely believe those best practices are still relevant and valid, probably more than ever.
So what has changed then? Back when I wrote that article, microservices were the new hot thing. All the cool kids wanted to do it. I was lucky enough to be part of a microservices migration at the company I was working for at the time. Today, many companies are moving back to monoliths because the benefits of microservices are often outweighed by the complexity of coordination and communication. As a result, the new trend seems to be going back, or at least questioning whether microservices were the right choice in the first place.
More often than not, when I am doing consulting and I mention microservices, I get a strange look. Almost as if they are no longer relevant because organization X, Y, or Z migrated their systems back to a monolith. But architecture is not, and has never been, about trends or what is fashionable in the market. It is about trade offs and about what works best under the specific constraints of a given organization.
What all of this translates to in practice is simple. If I start a new project today, I will not start with a microservices architecture. This has always been my belief. Microservices from day one usually cause more harm than good. They introduce unnecessary complexity for a piece of software that no one is actually using yet. I would start with a monolith and stick to it. Chances are I will never reach a point where it truly makes sense to split it into microservices.
The main change in my perspective is that for a long time, the main reason I used to justify migrating to microservices was the size of the codebase. Looking back, this is not a strong reason on its own. You can have a very efficient, profitable, and large monolith and evolve it over time with no major issues. Today, I think migrating to microservices makes sense mainly under a few specific conditions.
The first one is team size. In my country we have a very wise saying: too many hands spoil the soup. When too many people work on the same thing, the result usually suffers. As a team grows, the complexity of software development operations increases dramatically, especially when everyone is working on the same codebase. We can debate for hours about the size of changes, but conflicts will inevitably happen. In this scenario, it can make sense to let different parts of the team focus on different areas of the system and gradually allow those areas to become independently deployable units. This simplifies development operations at the cost of increased deployment complexity, which can usually be automated and monitored.
The second one is cost. Sometimes it is simply too expensive to run a monolith. Depending on load, you might need to run multiple replicas behind a load balancer. The number of replicas will fluctuate based on peak usage, but you will always have a baseline to serve normal traffic. In many systems, users mostly interact with a specific subset of endpoints that belong to certain modules. Those endpoints drive most of the load, while the rest of the system sees much less traffic. When you scale horizontally, every replica runs the entire monolith. In this case, it might make sense to extract the high traffic parts into separate services and allow them to scale independently on smaller or cheaper infrastructure, while the rest of the system runs on a relatively static set of replicas, making the cost much more predictable.
Another valid reason has to do with security and compliance. Sometimes a small part of the system handles data that requires much stricter controls, such as payment information, personal records, or any kind of regulated data. In a monolith, this usually means the entire codebase and a large portion of the team need to operate under those constraints. By extracting that responsibility into its own service, you can significantly reduce the surface area that needs to be audited, secured, and monitored. This makes it easier to apply stronger access controls, comply with regulations, and limit the impact of potential security issues, while keeping the rest of the system simpler.
In any case, these decisions must be driven by data and realistic estimates, not by throwing arrows in the dark.
I am sure I missed many other valid reasons why migrating a codebase, or part of it, to microservices could make sense. I would love to hear your thoughts. Also, if you like what you read or resonate with my opinions, why don't you subscribe?, it's free!.