When the development team gets ready to create a new piece of software, they have code with a certain structure in mind. Functions and classes are neatly divided into files and packages, placed in folders. As a result, the output is a well-organized, logical collection of functions scattered through hundreds of text files. The code from one file can easily interact with the code from another file, without any limits.
This structure is very convenient to use: a developer writes a component, puts it in the right folder, and reuses it in other parts of the system. That is a living embodiment of the engineering principle known as DRY, which stands for “don’t repeat yourself.”
This organization of code when everything is stored in one place is called “monolithic architecture.” The monolithic architecture has its heterogeneities in the form of packages, files, and modules. In general, such code is a huge rock consisting of veins, crystals, and other inclusions.
Table of Contents
What is the most accurate monolithic architecture definition? A monolithic application is often defined as simply a monolith. It is software delivered as a single WAR or Node app with a single entry point. Let’s imagine a classic online store. Standard modules include UI, business logic, and data layer. What are some of the methods to interact with the service? They include REST API and web interface.
When building a monolith, all these things will be managed within the same module. We didn’t write “same process” as that would not work in case multiple instances of the module would be running for higher loads.
To compare monolithic vs microservices pros and cons, we should have a look at the perks and pitfalls of each architecture first. The huge benefit of a monolith is that it is easier to implement compared to some other architectures. Often, engineers have to waste plenty of time deciding on how interprocess communication should look. In a monolithic architecture, you can quickly start implementing your business logic.
You should also consider the so-called end-to-end (E2E) tests. They stand for examining entire flows – like logging onto a store’s site or purchasing a product or service from this store. In a monolithic architecture, such tests are way easier and quicker to perform.
The monolithic architecture diagram above should help to understand the essence of monoliths. Speaking of operations, it is important to say that monolith is easy to deploy and easily scalable. For deployment, you can use a script that loads your module and runs your software solution. Scaling is achieved by placing Load Balancer in front of multiple instances of your software. As you can see, the monolith is quite easy to use.
Now let’s look at the negative aspects of monolithic architecture.
Making changes in one place of a monolithic program can cause damage to other parts. The point is that components in a monolith architecture can have complex and non-obvious relationships. Classes and functions in code may acquire multiple, non-obvious relations which can be easily broken. So, what are some of the issues with monolithic architecture?
Trying to change something in the code can take a lot of time and have far-reaching consequences. For example, a function you change may be used in a number of other function blocks. Even if the connections between these blocks are quite obvious, you have to check and change all the dependent blocks correspondingly. If there are other blocks connected to these blocks, you have to go further down the chain, check, change, check, change, and so on.
Monolithic applications fall with a rumble, often paralyzing all the business processes. Even if the error takes place in the code of a small and insignificant operation or process, in case of failure, your whole system can lay down.
Of course, not every simple mammoth hunter can carve the face of a tribe leader out of a rock. It is the same with monolithic code. Because of their complexity, monolithic apps require a qualified engineer or team of engineers with a deep understanding of the inner code functionality. This understanding is gained either while working on the project for a while, or by reading the project documentation. The documentation is often incomplete, erroneous, and does not reflect all the necessary information about the system.
So, it turns out that a monolithic program can be handled well only by those who have spent a lot of time with it or doing similar things. Newcomers or dummies have to spend a lot of time figuring out how the program works, and there is no guarantee they’ll figure it out. Now imagine if all of your key experienced developers were hired by a competitor. This could completely paralyze code development for a long period of time, or even worse – kill your business!
One approach that solves all problems mentioned above is microservices. They speed up, cheapen, and simplify development processes. Let’s dig deeper into microservices architecture's pros and cons.
A microservice is a tiny program running on its own server and working on just one type of task. For example, it could be a warehouse microservice that provides other programs with data on the stock of products in your store. Another example is an authorization microservice, which takes users’ keys and passwords and decides whether to provide the user with access to the system or not. Finally, it could be a microservice for sending text messages.
Any complex system can be broken down into tiny pieces that communicate with each other. Services can talk to each other any way they want. For instance, by throwing raw TCP packets to each other, calling methods via HTTP, or using a smart and convenient message delivery system like RabbitMQ.
It will be easier to understand the essence of microservice with the help of our example. Let’s look at the online store as an example. Initially, we have the UI, the business logic, and the data layer.
The difference from the monolith is that all of the above have their own service and database. They are loosely coupled and can interact with different protocols (e.g., REST, gRPC, or messaging) through their boundaries. The advantages and disadvantages of microservices will help you make your choice.
So, we are moving to the microservice architecture pros and cons. Why do many software developers choose microservices over monolithic architectures? Scalability, better data governance, enhanced information security, and the opportunity to become “language and tech-agnostic” are features that attract development teams. Let’s consider some of the perks provided by microservices and have a closer look at them.
Microservices should be really “micro.” There should be a small amount of program code in them. Ideally, there should be just enough lines of code so that a couple of programmers could write such functionality from scratch in 2-7 working days.
Any specialist can understand such an amount of code in a few hours and, if necessary, rewrite it completely in the shortest period of time. Firing an important and experienced employee won’t slow down your business as other developers can easily figure it out.
Let’s say your application is a store consisting of a set of services (warehouse, payment processing, cart, users, product display, etc.). In the middle of the day, your integration with the payment gateway fails. In the case of a monolithic architecture, your entire store may lay down (or it may not, but you won’t know that until the failure occurs).
In the case of a microservice, your business will be able to show customers products and form shopping carts with orders. When proceeding with payment, the user will see the message “You can pay for the order later.” Once the payment service comes to life, you’ll notify customers about it and some of them will come back and pay for the order. Even if it’s not 100% of your revenue, it’s not 100% of the loss either, as it would be if the monolithic system completely failed.
It is also possible to keep two versions of a payment microservice, working with different processing centers. If one service fails, you send all the requests to the backup, and you’re fine.
Say, your SMS delivery service can send messages through 15 communication channels, balancing the load between them. However, all these subtleties are not visible from the outside – only phone numbers and text messages are sent to the service input.
As a bonus, this approach makes it possible to write services in any programming language convenient to the team. Suppose you hired a specialist who writes apps in a rarely used language like Rust. You don’t need to retrain this expert to work with, say, Go, as they can simply write the necessary logic in Rust, pack it into a microservice, and give the other team members access to the feature.
Development becomes more transparent, and its complexity and cost are reduced. Microservice architecture is easy to fix – you always know exactly what and where it’s broken. If no data shows up on the stock of goods, fix the warehouse. If no SMS arrives, fix SMS. That is that simple.
There is little code in the service, so it is always easy to detect and fix the issue. In addition, this architecture is the benchmark for the DRY (don’t repeat yourself) approach.
Another question is whether any disadvantages of microservices exist.
A distributed system has some disadvantages. First, you have to deal with partial failures. Second, we have discussed the need to conduct end-to-end tests. You may face more tricky interactions at this point. Thus, the results might be inaccurate, making it more challenging and time-consuming to fix the bugs. E2E testing determines if various dependencies of an app are working accurately. One more disadvantage of microservice architecture is that implementing interactions between services can be more complicated.
Transactions are easier to perform in a monolith. The solution to this problem on microservices is Saga Pattern, but still too cumbersome to implement in practice.
There are operational overheads, and multiple microservices are more difficult to operate than multiple instances of a signal monolith.
In addition to the complexities mentioned above, microservices may also require more equipment than traditional monoliths. Sometimes microservices can outperform a single monolith if there are parts of it that require scaling to the limit.
Changes affecting multiple services must be coordinated among multiple teams, and this can be difficult if the teams are new to each other or do not interact regularly.
There is no definite answer. It all depends on your organizational structure. Do you have six or more teams working on one product? Then, microservices will do.
Do you have a team of around three developers? They will probably be good at building and maintaining a monolith architecture.
Other factors are speed of change and complexity. The high rate of modifications and high complexity are factors that make many businesses choose a microservice architecture. On the contrary, when you are not very familiar with the subject area, it can be useful to start with a monolith architecture. Just do yourself a favor and try to keep it modular. This will make it easier if you ever decide to split your monolith into multiple services.
About the Author
A technology expert and entrepreneur with 20+ years of experience in the web & software development business. Kosta used to occupy various positions, from technical to managerial & executive roles. Worked in both corporate and start-up environments. Currently runs Intellisoft Company as its CEO.
Also published here.