Microservices are one of the biggest buzzwords of recent years. However, it turns out that it is a bit like teenage sex: everyone talks about it, but nobody really knows how to do it. What does it take to make good use of this architecture? What conditions do we have to meet so that it’s something more than just an item on your CV? Read the article to find out.
Nothing new under the sun
Several years ago conferences were all about the Service Oriented Architecture. In a nutshell, it consists in building large systems with many logically divided services integrated with each other. The idea was to eliminate the main problems related to monolithic architecture. Most SOA implementations were based on or shifted over time towards the Enterprise Service Bus. The bus was responsible for communication routing, document mapping, handling different types of endpoints, auditing and security. The idea was noble, but the versatility of the solution turned out to be a double-edged sword. After some time the bus turned into another monolith. Centralisation, bottlenecks, both in terms of development and efficiency, and a single point of failure contributed to the growing criticism of the solution. I know cases where a 60-80-person team working on the bus turned out to be insufficient and a part of the communication had to be point-to-point so as not to block business projects.
The architecture of microservices, which is a de facto implementation of the SOA style, is based on the conclusions drawn while using the ESB model. The way of communication has changed dramatically. Replaced by point-to-point information exchange, the omnipotent bus is no longer the core of the solution. This is supposed to eliminate bottlenecks and enable independent development of projects.
Micro is not so small
How big is micro? Counting the number of lines of code is one of the most questionable methods of assessing the size of an application. But it will be sufficient for now. The most common answer to the question “how many lines of code should a statistical microservice have” is “1000”. I don’t want to act like an oracle and judge whether it’s right or wrong. But let’s resort to maths for support (back to the beginning of primary school). Let’s assume that the average size of one monolithic application (developed by a 20-30-person team) is half a million lines of code. If we divide it into components of a thousand lines each, in theory, we will get 500 services. This is not much less than the giants like Netflix or Uber have. Across the whole company. Developed by nearly two thousand engineers. And we have 30. Does it mean that you have to employ additional 1970 people in order to switch to a new architecture? Or is it better to change the level of granularity?
Assuming that 3-5 people can work on one service, let’s divide our monolith, for example, into 8 applications. On average, each of them will have about 60 thousand lines. And this is getting more realistic. As a programmer, I can easily grasp an application of this size in detail. You can also implement a specific part of business and effectively develop it with a small agile team.
But you may start wondering. What is actually wrong with microservices? Why should I trust others? First of all, it is worth noting that their solutions work very well, which may be indicative that their reasoning is right. It is the availability of the platform that is the main reason for choosing this particular granulation. In the case of using synchronous communication between services, a phenomenon referred to as “temporal coupling” takes place. In order to continue processing a business transaction, it is necessary to obtain a response from the second service, which may request a response from the third one and so on. The greater the “synchronous depth of the system”, the smaller its availability.
I don’t have users. Are microservices the answer?
There are many myths surrounding microservices. If I were to believe everything I hear about them at conferences, I would probably insist that breaking up monoliths into microservices is the answer to public debt and world hunger. I don’t even have to tell you that it’s nonsense. (Or maybe I have to? Don’t blindly believe everything that you hear at conferences!)
What is the difference between microservices and the classical distributed system? Listening to informal discussions, one can conclude that it is an IT equivalent of boasting about the price or size of a car. “How many microservices do you have? Well, we have 400”. Frankly speaking, I’d rather have 40 decent ones than 400 sloppy ones just to have something to brag about in front of my friends. But who am I to tell you. The basic difference between microservices and the classical distributed system boils down to autonomy. The dispersed system, although it implements the process by means of many separate systems, conceptually it resembles a monolith. All systems are updated with a single implementation and often do not even support the unavailability of collaborators (applications which they communicate with). This is completely different with microservices. Each service has its own life cycle. Works on individual applications are carried out independently and implemented without coordination. It is often the case that a service we depend on is not available, because the implementation of a new version is in progress.
Autonomy is one of the best things microservices can offer. It enables truly agile and scalable development of the system. Discussions such as the following are now becoming a thing of the past: “You can’t implement project X now, because project Y is still being tested”. Unfortunately, this independence also makes microservices by far the most difficult architecture I worked with. The need to constantly work in the “design for failure” model and to anticipate any communication problems in advance is what baffles even the best programmers and architects. On the other hand, if the business is not ready to work in such model and insists on staying in the release model, microservices lose one of their greatest assets. You have to foot the bill, but the problems remain unsolved.
Where are the limits?
One of the most challenging tasks when it comes to implementing microservices architecture is to define their limits. The first point of reference is the Bounded Context concept known from Domain Driven Design. In every context there is usually a domain expert, who is often the business owner of the processes taking place there. As a result, reducing the size of the application to a specific business area which can be managed by one person translates into better organisation and consistency than if you need to reconcile different interest groups. Data ownership and stages in business process should also be considered. If two seemingly disconnected contexts affect the same data, this may mean that the division is artificial. However, it may also be necessary to designate a third independent context to manage data used in other processes.
These are the main criteria for dividing services, but the list is not exhaustive. If one function can be much more effectively implemented in a different technology (e.g. in a different language) than the main service, separating them should be considered. The same applies to scalability. Knowing that certain functions will be used very intensively, moving them to a separate component may be a good idea. Security is the third aspect to consider. If the requirements in this area differ significantly from one function to another, putting them into one application may not be the best idea.
What are the basic applicability criteria for microservices? Consider this architecture if:
- the business you work with is ready to abandon the classic release model,
- individual business units are able to implement projects autonomously,
- you need dynamic and asymmetric scalability.
Make sure you leave a comment below.