Going from a monolith to micro-services is often desired but many give up. How do you ensure this transformation without being drowned in difficulties?
Several teams have begun splitting their monolith into micro-services since the spaghetti code was no longer maintainable.
Other teams choose to start a new project since it is the best way to avoid slipping into the monolith trap.
In both cases, they suffer and do not see the benefits of the micro-services architecture.
We’ll find out why.
Micro-services add complexity at all levels
It introduces intermediate serialization / deserialization and data duplication that are a bit tedious to maintain.
Backward compatibility and testing policies between each pair of interacting modules must be chosen for integration.
The services should be deployable independently, with their own versioning and release cycles.
It is necessary to be able to follow a trace on multiple services in order to debug.
But they are not the worst.
Splitting an application is difficult
A good split is more than just a technical split. It is dependent on the product, so there is no magic formula.
Most of the time, the boundaries are ambiguous. Micro-services aren’t all the same size. There will be tiny ones as well as large ones.
When a split is too small, we pay a high price on all levels, and going back is tough. We are looking for a relevant and long-lasting split.
Let’s take a look at the most common obstacles during a transition to a service-oriented architecture.
Traps to avoid
- Divide by small edge parts. It’s not very engaging: more painful than useful
- Make synchronized releases / deployments for all services. It means development cycles will always be correlated and therefore slow.
- Over-design infrastructure. Overcomplexity slows teams down.
- Start with no experience on the subject. Decision will be more difficult.
You do not need micro-services
As we’ve seen, it’s not “free”. To set up and maintain the system, you’ll need knowledge and people.
It is a solution at scale for large products and large organizations.
Thankfully, this is not the only option. It is preferable to choose an alternative that is appropriate for your product and your organization.
The alternative: macro-service
A macro-service, with an “a”, has the same properties as a micro-service but bigger.
The advantage of a macro-service is to minimize some difficulties with micro-services like dependencies, split stacktraces, etc.
This makes it possible to gradually move towards a service-oriented architecture. The size and number of macro-services will depend on your needs and your staffing.
Great, but how do you go from a monolith to macro services?
It is a straightforward iterative and incremental strategy. It goes like this:
- Divide the code into two parts of roughly equal size. If necessary, duplicate the code.
- Make a different container for each parts to obtain two macro-services.
- Adjust the infrastructure and organization
- Once stable, repeat with one of the macro-services.
The goal is to deploy the new architecture into production to validate a division. It allows adjusting the solution (routing, dependencies, tests, logs, deployment, versioning, etc.) before making a new division.
It is critical to accomplish a gradual transformation by aligning the technological and organizational sides.
Do not underestimate the complexity of a service-oriented architecture. The best way to succeed is to integrate people who know the subject.