Istio is moving back to the monolith, but it doesn’t mean you have to do the same
A couple of days ago, software company Istio confirmed they are moving back from a microservices architecture to something much close to a monolith to ease their product development and match some business requirements with less effort than before. The subtle irony is that Istio is a widely adopted product by DevOps teams to manage microservices architectures indeed. This fact is not ancillary to their choice, as we’ll discuss in the following.
Reading the latest post from Christian Posta provides a clear understanding of the reasons behind Istio architectural choices why they had to reconsider them in favor of more manageable releases and ease of deployments.
It is a well-written article even if a bit biased on Istio choices and suggests this makes a point. I do not agree it should be extended as an approach because IMHO their use case is quite peculiar, but let’s share a few thoughts with no further ado.
Istio is an open-source service mesh with architecture that can split between data and control plan. Many services within the platform impact both these two components. Their separate development required a lot of effort to be provided by the team.
What happened to Istio, and why they decided to step back from microservices?
The biggest and probably most relevant problem they faced is, in my opinion, related to domain separation. We know that walking the path of microservices starts with asking ourselves, “what is within a microservice, and how many of them do I need?”.
It is basically the well known “how micro is my micro service” problem.
The best guideline so far comes from Domain Drive Design (DDD) movement that, in recent years, pushed application architects to recognize business domain boundaries within architectures and enforce them using public APIs as interfaces. When you found this separation of concerns, then defining micro-service boundaries becomes a trivial task because they are precisely domain boundaries. Finding domains takes to finding dependencies in your services.
Following this approach, you should find yourself without any dependency loop. Avoiding loops, even if not mandatory, has a considerable impact on coupling: it enables you to model our architecture at a different level of detail, treating as black boxes everything is not relevant and putting it behind interfaces.
Dependency loops sometimes are not avoidable but create coupling between services, then blurring their boundaries, and suggesting they should be consolidated into a single module.
Looking into Istio architecture, it is quite challenging to draw a sharp line between specific domains within the platform. Service data flowing from Pilot to Citadel, Telemetry, or Policy and back to proxies create a closed-loop between each component.
Istio chose to consolidate many functions back into a single deployment because their domain happens to be not well defined: coordinating a such number of coupled services would require a service mesh tool able to ease out communication between different components. It would require having something just like… Istio.
Istio switched back to monolith because they couldn’t leverage Istio
Does the case for Istio apply to every project?
Istio team made the right choice based on their needs, complexity, and, most of all, the absence of a tool such as Istio, which makes coordinating small microservices feasible with little efforts.
Probably any dev team out in the wild world lives a very different story from Istio. In almost all of the practical use cases, the benefits of microservices in terms of lifecycle management decreased costs and increased speed of development and scaling, greatly overcome communication issues.
Developers tend to be much more comfortable with microservices because they can be managed entirely by a small two-pizza team, reducing the need for endless meetings and improving happiness.
In the end, one point deserves some discussion: development speed when building monoliths, which is prone to misconceptions.
Is the monolith a suitable approach for faster development cycles?
Well, it depends. Monolithic architectures offer the illusion of having every code function, and the data model under the same package means simplicity. Unfortunately, this is true just in the short term: as soon as the codebase increases, it would require strict rules to ensure maintenance, a lot of documentation to share knowledge, and a vast test suite to avoid regressions.
Moreover, following a monolithic approach means a bigger team to be coordinated because software requirements need to be implemented without impact on existing functions, and every aspect of your codebase needs to be accurately understood to avoid breaking things when releasing updates.
Microservices means smaller teams that rely on more agile knowledge sharing since codebase for each service is small. This is a considerable advantage of microservices architectures that are going to hit your team far before you have to consider other benefits such as scalability, reduced operational costs, and deployments.