Imagine a small café owner trying to be present in every aspect of his business. He takes orders, polishes a coffee machine, serves drinks, and smiles for every customer. All goes well until the number of visitors, and the number of tasks starts to grow. Or the ice cream or coffee-making machine, or any other mechanism starts to call for a repair guy. Now it is a pain to watch this poor man run from counter to counter and see the energy and friendliness fade away step by step.
That resembles the way monolith software operates in some way. It is like a jack-of-all-trades from the world of software machines that can deliver all business functions as a single unit. However, monolithic apps seem to lose their popularity in contrast to microservices, which allow for constructing heavyweight custom software development solutions using “Lego bricks”.
In this article, we will examine two approaches to choose the most relevant one for your needs.
What is a monolithic application?
With monolithic software, a single codebase comprises multiple interconnected and tightly coupled with one another modules. Despite being an autonomous unit, which resembles a block of stone (or a monolith, hence the name), it consists of three parts:
- A user interface, which contains JavaScript code and a collection of HTML pages;
- A data layer - an organized collection of data within a relational database management system;
- A server-side app retrieves and processes database requests and sends back a response containing the generated HTML and delivers the requested content to the browser.
Once again, as a single build with a large codebase, a monolithic system encapsulates business logic and organizes it as a combo of layers and their dependencies. What does that mean? If developers need to make any changes to the system, they need to modify and deploy an updated version of the server-side app. This affects every single part of the software and the solution in its entirety.
Additionally, all the concerns like login, caching, memory management, and security features are addressed from the ground up and don’t require additional development efforts as they are applied to the whole system once.
The development process of a monolithic application regularly involves small cross-functional teams working on a single executable artifact. Traditionally, the Software Development Life Cycle (SDLC) is broken down into the following stages:
- Requirements gathering
- Design
- Development
- Testing
- Release
To deploy a monolithic application, it is necessary to collect some executable artifacts from the source code in the repository and transfer them to the server. Even if there are slight changes in some modules within an app, it is necessary to redeploy an updated version of the whole application.
Depending on the type of programming language, interpreted or compiled, the files can either go through the compilation stage or omit that step. If they do, this output is compiled into binary files and uploaded to the server as jar/war files (for projects with Java stack) or even .exe files. If they don’t require compilation, they are transferred directly to the server (as with the Node.js runtime environment).
Another everyday use case is the use of a docker image. To put it simply, it is a virtual operating system in miniature with either a set of everything that is needed to execute these files (a Java virtual machine or a Node.js interpreter, depending on the chosen tech stack) and a kit of these files.
To sum up, this type of architecture is used to create an indivisible unit without rigid boundaries between its constituents. At first glance, one might think that there is no solution more holistic and more reliable than a monolith-based one. However, don't jump to conclusions at that point. Instead, let’s consider the benefits and possible shortcomings of that approach first.
Benefits of monolithic software architecture
- Ease of deployment. Developers need to handle a single unit of deployable files or directories just once instead of updating separate components step by step.
- Easy access. A centralized code and memory make it easy to implement business logic and reduces the scope of cross-cutting concerns.
- Ease of debugging and testing. End-to-end automatic testing doesn’t have to overcome any significant hurdles since there is no need to orchestrate different runtime environments and technologies.
- High security. A monolithic system ensures the integrity and confidentiality of the information it processes and transfers.
- High performance. With code simplicity, shared-memory access, and the possibility to use one API call to address the desired goal, a monolithic application has better throughput performance than distributed systems.
Pitfalls
- Tightly coupled modules. Even a slight change in the code affects the whole system. So, it is hard to isolate particular services for independent code support, which, in turn, retards the development process. For instance, a single bug in any module causes the system to revert, go offline, scale back, and be fixed as a whole.
- Scalability issues. Scaling individual components with dependencies is a challenge that can interfere with the project’s budget and timelines and cause substantial downtime. The most viable way to complete the task is to scale it as a whole.
- Lack of operational agility. Since the repeated deployment of software artifacts becomes a barrier to swift change, organizations can lack responsiveness and flexibility in their business.
- High entry barrier for new developers. It is incredibly problematic to grasp the logic of the entire system, where each element is dependent on the others. This is especially the case when the original developers are no longer around, and the number of modules grows exponentially.
- Limited access to new technologies. Tackling software modernization issues or adding new technologies to a complex monolithic application forces the entire application to be rewritten.
What does the above combination of pros and cons mean for an Enterprise X? Building another crucial piece of a small application or validating a business idea with a monolithic development cycle is relatively easy. However, growing enterprises can’t afford the risks of downtime, scalability hurdles, lack of agility, and other critical issues. Luckily, there is a way of avoiding the pitfalls of a monolithic approach to software development.
What stands behind microservices architecture
While business logic with monolithic architecture resides on a single system with a single deployment unit, microservices divide it between different “services”. For instance, if you recall the way people work on assembly lines, that can illustrate the microservices development approach. One guy may weld the front frame. Whereas, the next one applies red paint, the next one begins inserting the components, and so on.
These small service chunks have their logic, database, and standalone deployment mechanism. So, if you require 100 different functionalities for your application, it is necessary to deploy an equal number of microservices. The interaction between them can be facilitated by lightweight REST API protocols that involve synchronous request-reply patterns. Another path is to opt for asynchronous communication using Kafka, which supports queue-based communication.
So, despite having a particular job, microservices are designed to work together in one distributed environment. That also means that separate components within microservices-based architecture can fail without negatively affecting the rest of them.
How does it work? For instance, a typical e-store has separate functions to support each buyer’s journey. Think product navigation, a search bar, shopping cart, wish lists, and so on built as individual microservices. If there is a bug in one of these functions, other functionalities will remain intact and accessible to each shopper.
That’s where the core idea behind the microservices-based approach to architecture lies. It aims to reduce the dependency between the services and make them loosely coupled, thus surpassing the pitfalls of a monolithic application.
What benefits do microservices bring to businesses?
- Ease of understanding. Since the app is divided into separate elements, each developer can focus on a specific business function without grasping the entire architecture.
- Better resilience. If one microservice goes down, the rest of the functionalities remain unaffected.
- Enhanced agility. Each developer can adjust a particular service in isolation, which removes friction from the entire operations and paves the way for experimenting.
- Scalability. Instead of scaling the entire application when the demand for specific services grows, developers can scale only one element at a time.
- Flexible technical options. Each microservice can use different runtime environments or technologies based on business requirements.
- Faster time-to-market. A microservices-based architecture allows for shorter development cycles, faster deployment, and adjustments.
Our DevOps experts have a solution! Share more details about your project, and we will get back to you shortly.
With microservices, there is several concerns to consider as well:
- Complexity. A distributed system is much more complex than a monolithic one. Its complexity increases along with the number of microservices.
- Expertise. Skilled developers are required to deploy microservices and manage their intercommunications.
- Complicated deployment. As microservices are written in various frameworks and languages, they require substantial resources to accommodate each service requirement.
- Security issues. The flow of inter-services communication via API gateways raises data protection issues.
- Testing and debugging hurdles. It is necessary to inspect each service log one by one to pinpoint the exact failure dot in most cases.
- Cultural changes. When opting for a microservices-based architecture, giving up on a traditional approach to development is necessary. That affects the way people work as each team has to deal with isolated service clusters.
Monolithic vs Microservices Architecture:
Which to Choose?
Well, both architectural approaches have their pros and cons. However, there are specific things to consider before making the final decision. So here’s a quick recap of their most vital points in terms of different requirements:
Criteria | Monolith | Microservices |
---|---|---|
Team size and composition | One small team. No plans to grow the team | Several sub-teams. You plan to expand the development capacities with time |
Expertise | Proficiency in one of the back-end programming languages. Lack of microservices expertise | Proficiency in DevOps, CI/CD, cloud-native dev |
App complexity | Small app with straightforward business logic | A large app with multiple modules and complex user experiences |
Scalability requirements | No strict scalability requirements | A large-scale solution to accommodate business growth |
Time requirements | Fast iterating is a must | Enough time to go through a thorough planning stage |
The industry seems to be moving from monolith to microservices by giant leaps because of each player’s added value. Multiple tech giants have already adopted this approach but with certain peculiarities. Let’s find out about the most prominent use cases so far.
Top microservices apps in action
Amazon
Amazon.com retail website used to be a sizable architectural monolith in 2001. It switched to microservices due to several issues including development delays, coding challenges, and inability to meet scaling requirements at seasonal peaks. They assigned a small team to one particular service with high workload requirements and ensured their communication via APIs.
Paypal
The scope of operations of this service doesn’t leave room for a monolithic approach to development and deployment. Paypal has to cope with unprecedented user demand and provide excellent customer service along the way. For that, the company leverages a structured approach to different workflows using microservices. It resides on a Node.js runtime environment, which serves to create a distributed system for isolated workloads.
Spotify
As a complex app that serves more than 80 million users every month, Spotify opted for a microservices-based architecture to avoid the downsides of a traditional approach to development. By dividing all services into small and lightweight components, the company refined its offering and ensured high-level customer experiences under heavy load.
Monolithic Application vs Microservices - Technologies
Technologies | Monolith Architecture | Microservices Architecture |
---|---|---|
Languages | Java, .NET, PHP, or Ruby on Rails, Python/Django, Node.js (rarely), Go (rarely), JavaScript, Angular, React.js | Any language (but you can rarely meet a microservices-based app on PHP/Ruby on Rails) |
Database | Any relational database: PostgreSQL, MySQL, etc | Amazon Redshift, Redis |
Other | Groovy, Scala, Apache/Nginx, JRuby, and other tools | Kafka, Docker, Jenkins, Amazon EKS, Amazon ECS, Kubernetes, Lambda, git, containers, gRPC, Istio, service mesh |
So, which architecture is better? There is no one-size-fits-all approach to all of the organizations. The answer depends on the needs of each company. To save your time and effort, we’ve collected the most crucial characteristics of each approach in the below table.
Monolithic Architecture vs Microservices Comparison
Criteria | Monolith Architecture | Microservices Architecture |
---|---|---|
Understanding | Too complicated to understand the whole system at once | Ease of understanding a small service chunk |
Scalability | Limited | Highly scalable |
Flexibility | Strict technology confines | Apps evolve along with changing business requirements |
Deployment | It is necessary to deploy the whole app at a time | It is possible to deploy and revert individual clusters |
Maintenance | Difficult to maintain due to tight coupling | Easy to maintain due to loose coupling |
Testing | Automatic end-to-end testing is possible | Global testing needs to be coupled with testing individual components |
Operational agility | Lack of possibilities for innovation | Countless opportunities for innovation |
Resilience | If the service fails, the entire system goes down. | If one service fails, the app remains uninjured |
Development | Simultaneous development of the whole solution | The project team is divided into autonomous units |
Conclusion
As you can see from each microservices architecture example, there is a tradeoff in terms of the complexity and flexibility of each app. However, it is possible to overcome potential hurdles and decompose the complexity with enough technical expertise at your disposal. Other factors to consider are scalability and time requirements. A large-scale solution with complex business logic and vast interdependencies fits well with the microservices-based approach to development.
However, if your task is to test a new business idea and receive feedback from a small MVP, it is excellent to start with a monolith. For instance, one of our clients started their business with a monolith application written with Node.js (rarer for the industry.) Unfortunately, as the system evolved, its legacy code started to delay change and innovation, which reflected the inability to cope with growing traffic volumes.
To address the issue, one of our development teams decomposed the monolith into microservices written in TypeScript. Another team was involved in writing microservices in Golang, which enabled us to achieve 10x performance gains for selected components.
Discover how we’ve helped the client to optimize the system’s performance through technology.
Indeed, without proper microservice's expertise, applying this approach would be impossible for the client. If you want to follow their strategy but don’t know where to start, contact our expert development team to find out the details.