Ever since we began hearing about microservices, there has been a lot of talk about their suitability, their advantages, their implications and, above all, their size. The fact that the word microservice comprises the prefix micro makes many people think that microservices must be precisely that: micro. In fact, the concept behind the term is much wider and complex. In this post we will try to explain what size means when we talk about microservices.
Microservices are basically an architectural strategy that strives for agility in software development by dividing the functional scopes of a product such that each functional grouping can be developed, evolved, deployed, and maintained independently from the rest and supported by a team specializing in that and only that functional area of the business. Now, the key is to correctly define those divisions or partitions of the technical solution in order not to create problems we did not have before (when everything was part of a single “monolith”). Let us see then what differentiates a monolith from a microservice.
Monolith or microservice
Let us begin by analyzing a hypothetical situation in which the best solution has to be found for a complex business comprising many processes. These processes are somewhat independent from each other – although they also talk to each other. In order for the whole to work smoothly, all these processes must be choreographed perfectly. What would be the best architectural solution in this case? A monolith-based solution or a microservices-based solution? Let us see the differences between both options from 9 different perspectives:
- Separation of technical functions: A technical function is anything that is not directly necessary for running the business, such as log management, escalation, service repository, routing, availability, monitoring, and so on. How are they performed?
- Communication latency: What delay does information suffer when it has to travel between different parts or modules of a solution?
- Data consistency: How much time does it take the readers of a piece of data to get the updates thereof? Can changes be transacted?
- Ease of evolution: How does a module’s evolution affect other modules? How easy is it to avoid the risk of impacting other modules?
- Team specialization: Can we have teams specialized by business processes or do teams need to know all the processes that are supported by the solution?
- Automation: How easy is it to automate the deployment of the solution?
- Architectural quantum: How big is the minimum deployment unit when a change is made?
- Functional observability: How easy is it to observe the functional behaviour of the solution?
- Technical monitoring: Are performance issues easy to detect?
In the case of a business having many processes that need to be supported by a technological solution, it is preferable to design the solution using a microservices architecture. Let us see why:
Separation of technical functions
- From the point of view of the separation of technical functions, in the particular case of monoliths many of these functions (such as e.g. routing) are performed within the framework of development, which by definition entails a high degree of coupling between the business logic and the framework itself. This gives rise to well-known framework-related monolith evolution problems. If the framework does not evolve, the monolith might not evolve either or, conversely, might be forced to evolve by the framework.
- In the end, all of this results in added costs. In the case of microservices, many of the technical functions are performed by platforms that are in most cases Kubernetes-based, something which guarantees that they will be extremely uncoupled from the business logic, something which in turn promotes the overall adaptability of the solution. 1-0 to microservices.
Ease of evolution
- The ease with which a process can evolve without affecting the remaining processes is much more evident in the case of microservices, since it is an architecture that guarantees, at least at this level, software cohesion. This is something much more difficult to ensure in the case of monoliths, particularly when they are already a product that has been evolving and debugged for some time.
Team specialization by business processes
- Another useful characteristic of microservices is the chance to specialize the development teams by business processes, something which brings the value layer closer to the teams. This need becomes more complicated in the case of large monoliths with many processes, where a single team cannot specialize in so many business processes. This often leads to the antipattern of having several teams, each specializing in one business process, writing on the same monolith, i.e. the same code.
Architectural quantum
- The architectural quantum of a monolith having many processes is always very large because the code needed to support a lot of processes is necessarily big. This is problematic because it forces deployments to encompass the entire code even if the changes are small. This situation often leads to choosing to make deployments only when the changes are significant, which in turn negatively impacts the frequency of deployments and the time to market. On the other hand, the quantum in the case of microservices is much smaller, which means that, from this viewpoint, this architecture is also preferable for dealing with situations involving many business processes.
Technical monitoring
- Technical monitoring is easier to carry out in the case of microservices than in the case of monoliths because, despite having to monitor many more components, it is easier to identify those whose performance has degraded and even to know which business processes are being affected by such degraded performance.
Latency
- On the other hand, it is true that microservices have latency degradation issues, as it will always be worse to have to access the network to share information than to do share it via the memory of a process or by communication among the processes of the same computer, as is the case with monoliths.
Information consistency
- Another aspect where microservices complicate things is information consistency. Since microservices is a distributed architecture, it is not possible to guarantee the transactionality of the operations among several microservices. In addition, even if consistency is eventually achieved, this still does not guarantee that the times in the distributed updating of a piece of data will be short. Here, monoliths are the best solution.
Functional observability
- Functional observability is another capability that becomes more complicated in the case of distributed architectures. If the complete execution of a business process is distributed among components, it is thus difficult to reconstruct their behaviour to detect anomalies, etc.
Automation
- Finally – and also on the debit side in the case of microservices, automation becomes complicated when a multitude of components, each with its own pipeline, have to be deployed. This is opposite of what happens when only a few modules have to be deployed, as is the case with monoliths.
The first conclusion we can draw is that if we are developing a technological solution that supports many business processes that are relatively dependent on each other, we should choose an microservices-based architecture as it favours adaptability.
This explanation also supports breaking down a big monolith into several microservices with the aim of improving the adaptability of any business processes that might require adaptation.
However, what does relative dependence mean? Two business processes can be implemented in different microservices insofar as they permit an eventual consistency of the data they share and good latency is not a requisite.
Monoliths or microservices
Let us see what happens when our business case problem consists of few processes and does not require large amounts of code.
First of all, since the problem is not complex (as it only consists of few simple business processes), we can no longer say that it is a monolith proper; if anything, it would be a microlith (a small monolith).
In this case, thanks to the table we can see that the situation changes. Now we can see that the microlith does allow the only team that maintains it to specialize because there are only a few business processes. Since there is not much code, the evolution of each module is simpler and the quantum is small. Microservices, however, still have the same drawbacks that were discussed above. On the other hand, technical monitoring is still easier in the case of microservices.
Now we can ask ourselves: Is it not true that any software development always begins incrementally, business process by business process, such that they always start from small solutions?
From this basic principle we can draw the following conclusion: the development of a software solution should always start with a microlith. The architects will have to be ready to make the decision to split the microlith into microservices when it grows to the right size and to do it at the right time. When is the right time? When the microlith starts to look like a monolith, i.e. when the time to market or the frequency of deployment degrades or when its functional complexity cannot be dealt with by a just one team anymore and it becomes worth it to introduce the complexity added by eventual consistency, observability, and latency.
Conclusions
It makes sense to develop and implement solutions for business problems consisting of a multitude of processes via a microservices-based architecture since this will ensure adaptability.
All transactions should take place in the same microservice, particularly when it will not be possible to deal with the issues stemming from an eventual lack of consistency.
The development of a technological solution should always start with a microlith, whilst always maintaining the door open to creating other microliths/microservices around the first one or even to splitting the original microlith into several microservices when things start getting unwieldy and consistency and latency so allow it.
Comments are moderated and will only be visible if they add to the discussion in a constructive way. If you disagree with a point, please, be polite.
Tell us what you think.