Monolithic Architecture is a traditional way of building applications. This software architecture principle has both advantages and disadvantages. On the one hand, it can bring delight. On the other hand, it can cause disappointment. Let’s review its place in software architecture.
Monolithic Architecture Review
Typical Monolithic Architecture is presented in the picture above. The key characteristic of it is the fact that everything ( User Service, Flight Service, and Billing Service) is located inside in a single deliverable (a jar file in case of Spring Boot). These services are tightly coupled ( despite the fact that they have totally different functions) and use the same database.
The picture shows the most commonly used approach nowadays. Actually, in a monolithic architecture UI part can be packaged with backed service. As a result, UI, User Service, Flight Service, and Billing Service are located together in a single deliverable.
For scaling purposes, multiple identical deliverable units are deployed. The Load Balancer is responsible for routing requests to deployed monolithic services.
Advantages of Monolithic Architecture
- Simplicity of development. The monolithic approach is a standard way of building applications. No additional knowledge is required. All source code is located in one place which can be quickly understood.
- Simplicity of debugging. The debugging process is simple because all code is located in one place. You can easily follow the flow of a request and find an issue.
- Simplicity of testing. You test only one service without any dependencies. Everything is usually clear.
- Simplicity of deployment. Only one deployment unit (e.g. jar file) should be deployed. There are no dependencies. In cases when UI is packaged with backend code you do not have any breaking changes. Everything exists and changes in one place.
- Simplicity of application evolution. Basically, the application does not have any limitation from a business logic perspective. If you need some data for new feature, it is already there.
- Cross-cutting concerns and customizations are used only once. You should take care of cross-cutting concerns only once. For instance, security, logging, exception handling, monitoring, choosing and setting up tomcat parameters, setup of data source connection pool, etc.
- Simplicity in onboarding new team members. The source code is located in one place. New team members can easily debug some functional flow and to get familiar with the application.
- Low cost in the early stages of the application. All source code is located in one place, packaged in a single deployment unit, and deployed. What can be easier? There is no overhead neither in infrastructure cost nor development cost.
Because of these advantages, monolithic architecture is usually used in the early stages of application development. The reasons for that are the next ones:
- The main function of the application is to be profitable. As a result, it is important to quickly implement some POC (Proof of Concept) solutions to verify the application in the real world. Also, it is important to bring customers to the system. Improvements can be implemented in the future.
- The requirements are usually unclear at the early stages of development. It is hard to create meaningful architecture when the requirements are unclear. Real customers can define the business needs after some of the functionality already works.
The problems with Monolithic Architecture start to appear when the application becomes successful. The reason for this is very simple: the growth of the application. Usually, after some period of time, the Monolithic Application changes into another one because of the next reasons.
Disadvantages of Monolithic Architecture
- Slow speed of development. The simplest disadvantage relates to CI/CD pipeline. Imagine the monolith that contains a lot of services. Each service in this monolith is covered with tests that are executed for each Pull Request. Even for a small change in a source code, you should wait a lot of time (e.g. 1 hour) for your pipeline to succeed. And what happens when the pipeline fails for some reason? You wait again. All services are located in a single place. The size of the team is big. What happens when your colleague merges their changes? You rebase/merge and wait again.
- High code coupling. Of course, you can keep a clear service structure inside your repository. However, as practice shows, eventually, you will end up with a spaghetti code in at least a few places. As a result, the system becomes harder to understand especially for new team members.
- Code ownership cannot be used. The system is growing. The logical step is to split responsibilities between several teams. E.g. one team can work on Flight Service, another — for Billing Service. However, there are no boundaries between those services. One team can affect another.
- Testing becomes harder. Even a small change can negatively affect the system. As a result, the regression for full monolithic service is required.
- Performance issues. Potentially, you can scale the whole monolithic service in cases of performance issues. But what to do with the database? The single database is used for all services. You can start to optimize your database queries or use read replicas. However, there is a limit to this type of optimization.
- The cost of infrastructure. In cases of performance issues, you should scale the whole monolithic service. It brings additional costs for application operability.
- Legacy technologies. Imagine that you have the application written on Java 8. How much time is it required to migrate the whole monolith with multiple services underneath to Java 11? What to do with the tasks that are required to bring new functionality? It can be the case that the application will never be migrated.
- Lack of flexibility. Using Monolithic Architecture you are tight to the technologies that are used inside your monolith. You cannot use other tools even if they are better for the problem at hand.
- Problems with deployment. Even a small change requires the redeployment of the whole monolith.
Monolithic Architecture is optimal for small applications because of rapid development, simplicity of testing and debugging, and cost. However, when the system grows it can become an obstacle for business and should evolve into another form.
In the next post, microservices architecture will be reviewed.