Principles of Microservices – Decentralize All The Things6 min read
- In Programming
Decentralization is a tricky concept. There are many facets to it. In this article, I want to talk about decentralizing everything in a way it doesn’t hurt you or your organization.
When I think about decentralization the first thing that comes to my mind is Self Service.
Self-service is very important in a truly decentralized system. The people working on any service should not have to wait for any permissions or resources in order to do stuff. They should be free to work on their own.
This leads us to the Owner-Operator model.
This model is all about giving ownership to the team completely. In this, the team not only owns the service completely but also responsible for its evolution.
Make the team responsible for their decisions. Give them the power but also make them responsible for it.
There won’t be any other bug fixing team or deployment team or operations team. The team will own up to everything and will take responsibility for each and every part of the service.
This takes us to another connected concept of Internal Open Source Model.
Internal Open Source Model
Have you worked on any open source project before?
In that, you write your own little piece of code and raise a pull request to the owner asking them to include it. But the final decision of including your code lies with the owner of that project.
The same model should be implemented within the organization.
If one team requires something from the other team and they know exactly what they want. They can always write out that functionality and send a pull-request to the owning team.
But this is it. Their job ends here.
It is now the other team’s responsibility whether to take the code or propose an alternative or write something else. This way there is a clear boundary between different teams.
This is one way to start thinking about decentralizing the entire system.
Orchestration VS Choreography
This is another concept that needs to be looked at while designing microservices.
Let me explain you by giving an example of both the design models.
Suppose you have to create a Customer Enrollment flow. In this Customer Enrolls himself.
Once the customer is enrolled, a series of steps are performed. The Customer Record is created in the database. Loyalty account is created. A welcome pack is dispatched for the customer. And a welcome email is sent at the end.
This functionality can be implemented in a couple of different ways.
Let’s talk about the orchestration approach first.
As you can see that the above steps are a simple flow. So, in the orchestration model, a single service will own the responsibility for executing the entire flow.
This service will be at the centre and call different services at different stages.
This is the most widely adopted model that can be easily found in any organization. There are many pros to this approach as well.
Identifying the bug is fairly easy. You will know which part of your service is broken and then you can fix it at the source. Since all the business flows are enclosed in a single place, understanding of the system is pretty straightforward. Just by looking at the code, one can understand what is happening.
But these pros always have some cons.
In this model, one service acts like a God service with all the powers. It controls the flow of every other service. Sure it helps to decentralize different services but itself becomes a centralized authority telling other services what to do. This God class drains the responsibility from other services in such a way that they end up becoming just the wrapper over the database (simple data accessors).
All the logic resides with the God service. And this is not exactly what you would want in a decentralized system.
Decentralization means each and every component of the system have the same authority, same power. They should share equal responsibility and control.
Choreography design avoids the formation of God Services.
This is achieved by introducing some kind of message broker for events in between which decouples the tight coupling between different services.
In this approach, every component is aware of its own responsibility. They know their job and no central authority is required to tell them what to do.
The design for this will be something like the below image.
Here the Customer service only responsibility is to raise an event that customer has been created. Other services will be listening to this event and will start processing.
As you can see there is no central authority in this model. Every service is responsible for performing its own task. This provides good cohesion and loose coupling. However, there is one downside to this approach as well. The debugging is much harder.
Since every service is working on its own, its defect would take much longer to be identified. Let’s say Loyalty and whitemail worked fine but there was no email sent to the customer. In this case, until and unless customer complaints about the issue, nobody will know of this issue.
Of course, we can have external monitoring tools but that is the extra we have to do in order to make sure that all the services are working as they are supposed to. And these tools are expensive and requires additional maintenance.
For instance, we can configure the Splunk logs to look for the opening & closing of “certain text” and make sure those openings are being closed. And whenever it doesn’t found the required closing, it raises the alerts.
As we saw that decentralization is a tricky concept but it can be done by following the steps mentioned in this article.
I’m sure these steps are not applicable for all directly but the goals should be the same. It takes time to change the concrete ideas and adopt new ones.
So just to summarize the topics we discussed. You should always allow teams to be self-serviceable. Follow the owner-operator model for better control and responsibility. Use an internal opensource model to maintain control and authority over the service code. And last but not least choose between Orchestration and Choreography wisely. Both approaches are equally good but depend on the problem you are trying to solve.
I hope you enjoyed the article. Let me know in the comments.