Religions, laws, and conventions have been created to address societal problems just as new technologies are created to address technological problems. The microservices architecture is a new technological development to a technological problem. Unfortunately, the concept remains controversial among the software development community due to a lack of understanding about the history of microservices.
When developers fail to understand the history of microservices, they waste time and money in its implementation. This leads to the creation of numerous articles which curse the microservices architecture and its containers (i.e Docker and Podman), orchestrators (i.e Kubernetes and Nomad), and virtual computing management systems (Cloud Computing). Of course, the issues engineers face with these tools can be eliminated by understanding the purpose of microservices.
The Conceptualization of Microservices
The microservices architecture is a solution to the physical limits of a computer. In other words, the Laws of Physics — alongside the speed of light — physically limits the speed that an individual computer can run at. So what happens when you need to run software that exceeds the physical limits of an individual computer?
Scalability is the ability to increase the amount of operations a service can handle. As an example, a Web Server software sends (serves) pages to a user’s client. It does so by processing user requests (an operation) and then sending the page to the user (another operation). Scaling this Web Server means increasing the amount of pages it can serve in a given time period (i.e per second).
When the computer that runs the Web Server needs to scale, one method of doing so is by upgrading the computer. This upgrade — referred to as Vertical Scaling — increases the speed of the computer, which increases the speed limit of the Web Server. However, at some point, upgrading the computer becomes IMPOSSIBLE. As a result, we must scale the web server by running it across multiple computers.
Adding another computer to scale is referred to as Horizontal Scaling which is used in a Horizontal Architecture (HA).
In a similar manner to the cells of a human body, computers must exchange information using signals to process the same operation over multiple computers. This process of exchanging information is known as communication, and is used over a computer network to coordinate each service. Unfortunately, communication comes at a cost to processing speed called latency. An optimal microservices architecture implementation allows the developer to add power to a service using another computer, while still maintaining a low latency.
The following questions can be used to clarify the concept of microservices.
When Should I Use Microservices?
If your program has yet to be created, you must consider whether the implementation of microservices is worth it. Will your service become both
- Bottlenecked due to the physical limitation of a computer.
- Unable to be horizontally scaled through active-active load balancing (i.e cloning the monolith).
If so, implementing microservices is an objectively valid decision. Otherwise, if your program already exists (while failing to meet the criteria above), a microservices architecture is simply not necessary.
How Should I Structure My Code?
It doesn’t matter. Microservices is not about the code. It’s about the architecture.
Should I Use One Repository or Multiple?
It also doesn’t matter. Microservices is not about the code. It’s about the architecture.
With that being said…
Should One Service Depend On Another?
Let’s say that you split the Web Server into two microservices for processing requests and sending pages. When a user sends a request, it will be sent to the sending service which communicates with the processing service BEFORE the user’s client loads the page (from the sending service’s content). In this case, the sending service depends on the processing service.
So what happens when the processing service goes down?
In the worst implementation, users stop receiving pages because nothing is being processed. However, you can fix this by adding logic in the sending service to send an “experiencing server issues” page to the user (when the processing service is down). This allows the user to receive pages even when the processing service is down. Thus, a linear dependency is not the end of the world in a microservices architecture.
But when the sending service requires information from the processing service, the following scenario occurs.
The SRE will be paged in the middle of the night. Users won’t receive pages because the processing service is down, even though the sending service is up and… The sending service will go down as well. What happened? You created a circular dependency with your services.
Don’t do that.
Using the microservices architecture requires you to manage your dependencies in a similar manner to your code. Fortunately, programmers have created tools which manage dependencies among multiple containers of services (i.e Docker and Podman). These tools — such as Kubernetes and Nomad — are called container orchestrators because they orchestrate containers.
The significance of the container and the container orchestrator is that they are technological developments that solve complexities provided by the microservices architecture. These complexities are not avoidable unless you can develop a computer that is infinitely upgradeable. However, the development of microservice technologies hasn’t stopped at this point.
A container (of services) is to a computer as a computer is to a cluster. Such that a computer cluster manages multiple computers (called servers). Programmers use Cloud Computing to manage the computers within these clusters in a virtual manner. Stateful languages — such as Terraform — were created to manage the state of the cloud. So that’s why “Cloud Computing is made for scale.”
So What About The Database?
Your database is a service. So it makes sense to follow the rules established above. Don’t implement circular dependencies, even if doing so requires the usage of multiple databases and/or duplicate data. In practice, you are NOT likely to end up with the same schema for two separate services. Hence, the database per service recommendation.
No Need For Controversy
The controversy surrounding microservices can be addressed by educating developers on its conceptualization and being cautious in its implementation. The microservices architecture is another tool developers can use to solve technological problems: It should NOT be applied to every project that exists. Going forward, we must encourage developers to learn about the reason a given technology exists as opposed to focusing solely on how it works.