Microservices has been a buzzword for a couple of years now, and it is starting to become de facto architecture for many software companies. The question is why is that?
The world is changing, 5G technology is on outdoor steps, more people will work from home, more devices will use online services and every service will have to handle a lot more requests. If our architecture is not set up in the right way and scale easily, we may lose customers.
The goal of every software application is to be reliable, and reactive, and handle any load of requests thrown to the system without any downtime.
Until a couple of years ago, every software application was packaged and deployed as a monolith (one unit).
What is Monolithic Architecture?
The monolithic architecture is the default for software systems where we build the system as a single and indivisible unit.
A particular system is considered monolithic even if we split the software into multiple packages and projects for more modular development, but build and deploy it as a single unit.
Advantages of Monolith
- Simple to build and deploy: One continuous integration pipeline that will build and deploy an app in any environment we need
- Simple to scale horizontally: Having one app that we need to scale by running multiple instances of the same app behind a load balancer is not a very complex process
- Simple to develop: Implementing security, database transactions and interactions between services in the same app is an easy task
- Simple to monitor and collect logs: The process of monitoring and collecting logs from one or multiple instances of a single application is simple
- Easy to Test: The QA team can create integration or automation UI end-to-end tests with ease if they have a single application to worry about.
Disadvantages of Monolith
When the projects become very large, then the Monolith starts to show the bad side of the architecture. In particular:
- Large code base: When multiple teams are working on the same code base, problems start to happen, and many bugs and code conflicts will appear because there are times when teams will work on parts of the code implemented by different teams and the team that is implementing the code is not familiar with that part of the application
- Scaling Components as a group: If millions of requests per day hit one of our API endpoints, but the other endpoints do not, under the assumption that there is no way to horizontally scale only one service, we will have to scale the whole application. This means using and paying for resources that we do not need and use;
- Not resilient enough: If the app fails (e.g. memory leak), all the services related to the app will fail. This means redistribution of the request load on the other available instances that may also fail under the sudden increase of pressure. Having no responsive application is a bad user experience;
- Hard to update or implement new technologies: Updating a new version of a particular framework or tools as well as implementing services in other languages more suitable for the job is very hard. These updates may have a great impact on the application, it will be time-consuming to develop, test, and push into production. On the other side, working with old technologies is a step back compared to the competition.
What is Microservice Architecture?
Microservices as a concept is not a new one. In the last couple of years, microservices gained a lot of popularity and improved the business of a lot of software companies like Amazon, Netflix, and eBay. They have all adopted microservices and share their successful stories related to the transition from Monolith to Microservices.
Microservice is an architecture style that constructs an application from multiple small services that are developed, built, and scaled separately. Each service is a separate application with its own architecture, dedicated team, database, and Software Development Lifecycle in general (SDLC).
Advantages of Microservices
- Focus on a specific domain: Each service is focused on a specific application domain. Usually, the separation of the domains is done by using the so-called DDD (Domain Driven Design). Having this separation, the service will be developed by a dedicated team that will be focused on that service development only;
- It tackles the problem of complexity: Breaking down the application into small services give us the ability to do faster development, maintenance, and smaller and faster releases into production in order to satisfy the customer needs;
- Flexibility to choose different technology for every service: Having loosely coupled services give us the ability to build every service with the proper technology. For example, we can build one service with Java and the other with Node.js. Implementing the best software technologies available will be a boost for every company against its competition;
- Build to tolerate failure: The basic idea of microservices is to build resilient services in order to be prepared for service failures and handle them appropriately. In this concept, failures are part of the services. If all instances of one particular service fail, it will have a limited impact on the other services, i.e. the application may lose only one part of the functionality, but the rest of it will work just fine without any issues.
Disadvantages of Microservices
- Complex build and deploy process: Having multiple separate services requires having continuous integration pipelines, testing, acceptance, and production environments for every service and all of this needs to be maintained by per-service dedicated team (however Cloud tools and automatic Infrastructure provisioning scripts will help the teams act in a structured, organized and efficient way)
- Database per microservice: Having a separate database per microservice adds complexity in cases when we want to execute an operation that needs to add, update, or delete records into multiple microservices. Implementing distributed transactions in a microservice architecture is more complex than in the traditional database ecosystem. Nevertheless, there are patterns like Compensation or Saga that tackle this complexity and solve this problem;
- Implementing functional changes that span multiple services is hard: If we need to implement a new feature in our application that impacts multiple services, then we have to coordinate and talk with the multiple teams that work on the impacted services. The next step is implementing the changes; deploying, testing, and pushing the changes in production for all services in one go. Working with Microservices requires careful planning and coordination of the rollout changes to each of the services. Because of this coordination complexity, service contract versioning is always a good idea in a distributed environment.
- Complex to develop and require huge upfront investment: In many cases, companies are not adopting new practices or tooling because the initial effort required appears to outweigh the benefits. On the other hand, for long-lived companies, new technology must be adopted in order to keep up with the competition and industry standards
Adopting Microservices or Monolith for your next application requires a lot of research, planning, and understanding of the application domain. You have to calculate whether your development team is ready for changes, how your services will evolve, how your business will grow, and how many customers will use your services.
We hope that the list of positive and negative aspects of these two architectures will help you get closer to the right decision.