In this article, we will discuss the characteristics of a monolithic architecture.
We’ve heard about microservices and how they allow for a more agile software development approach to developing applications. However, there are still many software projects that use a monolithic architecture when developing an application. In fact, many microservices projects started out as monolithic applications. Let’s take a closer look at a monolithic architecture.
2. Introduction to Monolithic Architecture
The term “monolithic” is defined as a single massive unit. In software development a monolithic application is self-contained. All the of the components required to run the application are developed and deployed as a single unit, such as a WAR or JAR file.
Let’s take an e-commerce JEE application as an example. The application allows the user to view and order products. In such an application, you may have:
- a storefront user interface
- a few components such as catalog, order, and shipping as the business logic
- data access objects
In a monolithic architecture, all these components are enclosed in a single application that are tightly coupled. In this scenario, you would have a single code base that includes:
- Source code files, such as .java
- Configuration files, such as .properties, .yml and XML
- Build and dependency management files, such as Maven POM, Gradle, and ANT
Once the application has been tested, you build a WAR or JAR file and deploy it to a specific platform, such as a Tomcat application server.
2.2 Pros of Using a Monolithic Architecture
There are several advantages to using a monolithic architecture for your application. They fall into the following categories:
Application development is relatively simple as there is only one programming language and/or framework used. This works well with a small team of developers with expertise in a specific language.
This is a straightforward task as there is only one packaged application to be deployed.
Someone testing a monolithic application only requires access to the monolithic application itself to run his or her test cases. No other external dependencies are required as all the components are included in the application.
Managing a project that uses a monolithic architecture requires very little coordination as all the components are contained in the application, save external data sources such as databases, message brokers or web services. As so, there is little configuration required, as is not the case with a microservices architecture.
2.2.5 Level of Complexity
Monolithic applications are easier to comprehend, at least initially, as all the components required to run the application are contained within the application. New team members can learn the processes quickly and “hit the ground running” as there are no external components or dependencies (save data sources) that need to be accounted for.
You can scale up the application by running multiple copies and use a load balancer to manage traffic to improve response time and availability.
2.3 Cons of Using a Monolithic Architecture
As the application grows in size and complexity, a monolithic architecture may no longer be suitable, and the following areas may be affected:
2.3.1 Adopting New Frameworks or Technologies
If you decide to adopt a new framework or technology, it will require a rewrite of the entire application, since it is not possible to make a framework or technology changes piecemeal.
2.3.2 New Features are Slow to Market
It takes time to test, build and deploy large monolithic applications. Therefore, new versions are released infrequently. Releases are spread out so that they include a minimum number of updates. Doing otherwise would be impractical. This becomes a problem if you have a new feature or critical bug fix that you would like to release in a timely manner.
2.3.3 Level of Complexity
As an application grows, it is no longer easy to grasp how all the components work together. This means that a new developer joining the team will take more time to be productive.
As the code base grows, it is more difficult to maintain as several developers may work on the same code, causing merge conflicts. Resolving merge conflicts is a time-consuming endeavor.
As the code base grows, the application takes longer to start. This adversely affects the performance of the IDE being used, which in turn affects the productivity of developers.
Another issue is that it is all code modules are interdependent in a monolithic application. This means that making changes to one shared module or library may break other parts of the application.
If only one component of your application has a high resource requirement, it is inefficient to spin up multiple copies of the application, since you must deploy the entire application and not just the module that is getting taxed.
Application start time may affect the productivity of the test team since the application requires a restart every time a new build is deployed for testing.
Also, debugging certain bugs can be challenging, as all modules are interwoven.
2.4 Migration from Monolith to Microservices
When it becomes apparent that a monolithic application is no longer tenable, it may be time to migrate the application to a microservices architecture. In a microservices architecture, an application is split into a collection of small services and components. For example, an e-commerce application might be divided into a catalog service, an order service, and a shipping service. Each microservice runs in its own process and has its own database. Some of the benefits of using a microservices architecture fall into the following categories:
You are not locked into a specific technology stack. Each service can be implemented in whatever framework or technology stack best suited for it. And if you later find that another technology would be a better fit, you can make this change without affecting the other services that make up your application.
2.4.2 Delivery of New Features
Since services are loosely coupled, there is less risk when making updates to the code. This encourages innovation and the introduction of new features. This is a plus in today’s competitive environment.
2.4.3 Level of Complexity
Since the domain of a microservice is narrow, it is easier for a new team member to “get up to speed”, making him or her productive sooner rather than later.
2.4.4 Startup Time
The smaller code base of a microservice means startup time is faster, saving time for both developers and testers.
2.4.5 Parallel Development
Since each service has its own team of developers, parallel development is possible. Developers no longer have to wait for other components to be completed in order to develop and unit test their own code.
2.4.6 Frequent Deployments
Updates to a service can be deployed at a faster rate since they are independent of other services. This is a consequence of the loosely coupled nature of microservices.
2.4.7 Scaling is More Efficient
Each service can be scaled independently and according to its own resource requirements. For example, one service may require more memory while another may require more CPU cycles. Cloud services are available to meet these demands.
To summarize, a monolithic architecture is appropriate when:
- The application is relatively small
- The application is not very complex
- The development team is small
- The framework and technologies to be used have been predetermined
- There are very few external data sources
If any of these circumstances change, it would be wise to consider moving to a microservices architecture.