You were tasked with creating a new project.
As this project's scope is enormous, you decide to separate the components.
You tell yourself, "Wow, finally I'm one of those cool developers that work with microservices".
But you quickly fall into your first problem.
How the hell am I going to design this?
Lots of questions arise in your mind like:
- How should I separate my code?
- How will these services communicate with each other?
- How will the database be integrated into all this?
- How will the client communicate with the services?
You instantly feel discouraged and lost.
But, don't worry.
Lots of developers faced the same problems and, through trial and error, found the best practices to follow.
In this article, we will tackle the first question on how do we separate our services.
How do I separate my services?
The first problem we will tackle is how we will we separate or decompose our application into multiple services.
In general we want to decompose our application in a way that:
- Each service should be small enough to be owned by an autonomous team of 6-10 people.
- The architecture of be stable, meaning that it does not change often.
- Services must be cohesive, meaning that they should implement strongly related functionality.
- Services must be loosely coupled, meaning that each service must be an API that hides it's implementation. The clients of these APIs should not care about its implementations.
- Services should conform to the Common Closure Principle — things that change together, should be packed together. — to ensure that each change affects only one service.
- Services should be testable.
Now that we know what we want, let's look at the two main ways to decompose our application:
- Business Capability – You design a system that mirrors the organization structure. For example, in the organization for an e-commerce app, there may be teams such as orders, payments, and shipping team. Each of these teams can become a separate service.
- Subdomains – Sometimes the organization structure is inefficient, meaning that you wouldn't want to decompose your app on top of it. Instead you can look at the business domains and subdomains. Coming back to our e-commerce example, we may have a orders domain which has multiple subdomains such as payments, tax, and discounts. Each of these three can be a service while the domain will be orders. This is domain driven design in a nutshell.
Next, you might ask me, "how do I identify capabilities or domains in my organization?".
You can do that by studying your organizations structure, purpose, business processes, and areas of expertise.
What if I want to migrate a Monolith?
This is another very common problem, especially with large enterprises with old software.
The best practice is to implement something called the strangler pattern.
This pattern suggests creating some sort of facade behind the old monolithic system and over time taking out business capabilities to separate services.
This will reduce the risk of migration and will allow you to develop new services separately.
If you want more tips on breaking a monolith into microservice then check out this great article by Martin Fowler.
In conclusion, breaking down a large application into microservices can seem daunting at first, but following best practices can help ease the process.
To separate services, you can either decompose the application based on business capabilities or subdomains. The key is to make sure each service is small, stable, cohesive, loosely coupled, conforms to the Common Closure Principle, and is testable.
If you need to migrate a monolith, the strangler pattern is a best practice for reducing risk and allowing for gradual separation.
By following these guidelines, you can successfully design and implement a microservices architecture for your project.
Thanks for reading.