The choice in favor of a microservice architecture looks reasonable for business and attractive for IT. A service that is responsible for “your” piece of business is easier to control and develop separately from all the company's other services and systems: it is understandable, limited, separated from others and has a clearly defined task. This is in theory.
In fact, businesses are often unhappy with the result of such an implementation: instead of new features, a flexible system and rapidly executed processes, they receive increasing IT costs and endless refinement in a chain reaction mode. Moreover, with each refinement, parts of the system become more complex, and the connections between them become more complicated.
Andrey Putin, CEO of KT.team, explains why this happens and what to do about it.
Code architecture does not solve organizational problems
In a monolithic organization, it is tempting to attribute the cost or opacity of the process to the “wrong” technology or architecture. In this paradigm, it seems that replacing the system or introducing a microservice architecture should solve the problem. I am sure that not only KT.team, but also other IT companies often make such a request. Even if previous iterations failed, refining the microservice still makes sense, as it can improve the situation.
In reality, implementing a microservice architecture is often like trying to split a lump of frozen minced meat into pieces of beef, bacon, and pepper. No matter how much effort you put into cutting a monolith with an IT knife, the output will not be individual ingredients, but the same monoliths, but smaller in size.
The situation with IT architecture is exactly the same: if you divide a monolithic organization or set of functions into smaller pieces by eye, they will only resemble microservices in appearance.
Accounting as an example of architecture
Imagine running a large organization with thousands of employees. This organization has a large accounting department, divided into separate groups of accountants to perform various tasks: issuing certificates, registering employees, reviewing salaries, and preparing reports.
In IT terms, we can say that you have a service (accounting) and a set of microservices within it (target micro-departments).
All teams work independently, but exchange messages, such as sending documents or requests, as they complete tasks.
The Chief Accountant has an obvious need to follow all procedures and separate areas of responsibility — this way he understands what each group does, how departments communicate with each other, and what is the status of each process and document.
Moreover, even if, say, the payroll department is idle right now, its employees don't need to be overloaded with tasks from other micro-departments — this will disrupt well-established processes. From the point of view of the entire accounting department, one-day idle time is cheaper than switching them to processes that these employees do not specialize in.
This organization of accounting activities is very similar in meaning to microservice architecture. Each separate part of the system performs one separate task, has inputs/outputs, a clear internal process and protection against misuse.
How service architecture becomes a monolith
Now imagine that the company isn't that big. Yes, accounting still has the same set of tasks, but given the scale of the business, there is no need to “book” staff for each individual task. For example, a group of seven people can do all the tasks. Those who were engaged in personal income tax today will start paying bills tomorrow, update their reports the day after tomorrow, and then return to personal income tax.
Since the accounting team here is already much smaller, the classic “rituals” between departments are inevitably broken. According to the instructions, for example, you need to write a letter from the Certificate Department, record it in the register of outgoing documents, and then receive the letter from the Employee Registration Department and note the receipt in the register. But if the same person performs the functions of both microdepartments, the process looks absurd.
An attempt to get rid of this absurdity leads to the fact that the inputs and outputs of processes combine or disappear, and the boundaries between microdepartments are blurred. As a result, accountants seem to be working in microservices mode at any given moment, but in reality it turns out to be a monolith. It performs all the necessary functions, but each function is not transparent.
The situation could be even worse: the accounting department is in a mess, and no one really knows how processes work. Different employees prepare reports according to different standards; Masha counts reports in Excel, and Pyotr Semyonovich uses a calculator; new employees are brought into the system in three different ways...
When algorithms for solving ordinary problems are not spelled out in any way, each new person only exacerbates the resulting chaos. It is no easier to divide such accounting into micro-departments than a piece of frozen minced meat into its constituent ingredients.
Why microservices don't work correctly
Accountants from different micro-departments communicate freely with each other because they have a common context. For every accountant, the same term means the same thing. For example, “product” for both purchasing and accounting for material assets means the “article +price” link.
If this context is not available, internal accounting documents become a source of chaos: different micro-departments understand and take into account the same term in different ways. As a result, reports are filled with repetitions and gaps, and the entire accounting department's working time is spent constantly finding out where certain accounting items came from and where they went.
If everything is clear with the link “one department (one service) = one context”, what about the processes and documents that move between departments (services)?
In the sales department, for example, the word “product” does not mean an article, but a model in all its color variations. Thus, for an accountant, a black monitor and a white monitor will be considered two different products, and for a commercial department, two variants of the same product. Each department can explain why their understanding of the term is correct. And both will be right in their own way.
To avoid misunderstandings and at the same time not break the processes of each department, we need an “interpreter” who can correctly relate one context to another.
In a microservice architecture, middleware (bus) would be an analogue of such a translator. This is a separate service dedicated exclusively to establishing mutual understanding between other systems, even if they speak completely different languages.
There may not be a bus, so microservices will contact each other directly when required by the appropriate algorithm embedded in their logic. But this approach can only be used if you want to link a small number of microservices using a small number of integrations.
For complex systems with multiple recipients and senders, this approach is impractical, as it once again turns the architecture into a confusing monolith: each microservice “grows” into dozens of others and must take into account their processes and contexts. In this case, you won't be able to change one part of the system without affecting some other part.
With each subsequent change, it becomes more and more difficult to maintain and test such a system. The focus of developers is shifting from introducing new features to worrying about “no matter how things break”. Documentation for translating context between departments and services is getting more complex and growing every day. Improvements are being hampered, the best specialists are leaving, tired of working on the verge of failure.
What to do to make the microservice architecture work
In short, start with the company structure:
- form departments and micro-departments and determine whether it is possible to identify such micro-departments in all divisions;
- distribute areas of responsibility between micro-departments;
- create business processes with clear algorithms for each microdepartment;
- record clear entrances and exits for each microdepartment (requests, documents, messages);
- build clear relationships between micro-departments and their business processes;
- agree on the balance between micro-department contexts.
After completing all of the above steps, transfer the finished organizational structure to the IT circuit, where each microdepartment should be reflected in the form of a microservice: each microservice in its processes and interactions should reflect the processes and interactions of “its” microdepartment.
The microservice architecture is not suitable for all enterprises and not all departments. If a company or department is structurally monolithic, it is impossible to transfer their functions into separate microservices, no matter how tempting it may look.
According to the Melvin Convey Act, formulated back in 1967, “any organization that develops a system (in a broad sense) is forced to create projects whose structure is a copy of its own internal communications structure.”
At KT.team, we rely on this law when developing IT products for customers: we start by drawing the business processes that the product will be associated with, and only then we “go down” to the code level. Thus, an IT product is seamlessly integrated into the company's work and is effective in solving its problems.