We get these questions a lot from the teams we are coaching at my customer's work place
- How to create microservices?
- How to break down our big monolith into microservices?
- What are some of the best practices, etc.?
Monolith and it's limitations
Before we deep dive into that topic, let's try to understand the limitations of monolith applications. Monolith is usually a single large web app (traditional WAR/EAR file) which has everything built-in. A small code change in UI requires a build, deployment and test, even you did not modify code in business or data layer.
Also, if you would like to scale out a layer, it is difficult as it requires a deployment of whole application on new instances. Here comes the Microservices to solve those issues.
Why Microservices?
Microservice is an architectural approach of breaking application (functional decomposition) into smaller services where each service can be independently developed, deployed with no limitation to technology stack. They also can be scaled out without impacting other services.
Microservices Characteristics
When designing microservices, we need to keep the following in mind:
- Each service should be treated as a component and should be
independently deployable and able to be regression tested in isolation.
- Should be organized around business capabilities or domain.
- Based on Products, not projects – development team takes full responsibility of building software into production
- Decentralized governance
- Decentralized data management
- Infrastructure automation
How to migrate from monolith architecture into Microservices architecture?
If you are developing a large or complex application from scratch, start with microservices architecture by separating UI, business and data layers. If you already have a large app deployed to production which becomes a hard mountain to climb, you can address this problem in this way:
- Incrementally refactor your application into set of microservices without fully decommissioning the monolith app
- Implement any new functionality as Microservices
- Split the presentation components from the business and data access components
- Consider converting existing modules into services.
Best practices on developing Microservices
Here are some of the best but simple practices to consider when developing microservices:
- Design for failure (fault tolerance)
- Use one repository per service
- Each service should have independent CI/CD pipeline
- Each service should be loosely coupled
- Incrementally refactor your application into set of microservices when migrating from monolith
- Create a separate data store for each microservice.
- Deploy microservices in containers(Docker).
Challenges when implementing Microservices
Microservices architecture can be more complex than legacy systems. In turn, the environment becomes more complicated because teams must manage and support many moving parts. Let us see some of the challenges in implementing them:
- Tracing performance problems across tiers for a single business transaction can be difficult. This can be handled by correlating calls with a variety of methods including custom headers, tokens.
- Multiple databases and transaction management can be painful.
- Testing Microservices based application can be cumbersome.
- When more services are interacting, you increase possible failure points. So, they must be designed for fault tolerance.