17. October 2023 By Eleazar Alejandro Araujo
Saga pattern as the secret to creating a well-working system
You need to consider a number of things to successfully implement a microservice architecture, including questions like: How do we deal with transactionality? How should the system respond if an error occurs in the middle of a distributed business process? This blog post provides answers to these questions.
Transactionality in microservice architectures
Imagine you want to bake a cake. You take all the ingredients, mix them together, pour the batter into a tin and place it in the oven. Suddenly you realise that you forgot to add sugar. So you take the tin out of the oven, add the sugar and put it back in again. Sounds easy, right? But what if you had to bake the cake in a restaurant where there are ten different kitchen stations, each run by a different chef, and each station has to perform one step to make the cake? And to top it all off, each of them speaks a different language. Then baking a cake would be a real nightmare.
This analogy outlines the problem that a microservice architecture may encounter when carrying out complex business transactions. This is where the saga model comes into play.
What is a saga pattern?
A saga pattern is a design pattern used to execute complex business transactions in microservice architectures. It ensures that data consistency is maintained across multiple microservices by splitting a large transaction into several smaller, manageable steps. The pattern is called a ‘saga’ pattern because it works much like a story or a journey that is divided into smaller sections, each with its own ending that contributes to the overall outcome of the journey.
How does a saga pattern work?
In a saga, a complex transaction is divided into several steps, each of which is executed in different sub-transactions within a service. An event that provides information about the completed process is triggered at the end of each transaction. At the same time, it also initiates the next step in the saga that will be carried out by another service.
In the diagram above, we can see how a saga pattern works using an e-commerce order as an example:
The sub-transactions of the saga are carried out step by step within each microservice once the trigger is activated (i.e., the order has been confirmed). After each service has completed its internal operations, an event is triggered that initiates the next step. At the end, the entire system is in a new, consistent state.
If an error occurs in the middle of the saga, events are triggered in the opposite direction, which will initiate compensating transactions. These in turn ensure that the steps that were previously completed are undone for each service involved, ensuring that data consistency is maintained across microservices.
Types of sagas
There are two main types of sagas:
Choreography sagas are based on our example from above, where the microservices that are part of a saga interact and manage the entire process on their own.
A choreography saga could be compared to a situation like this: you meet up with a group of friends to cook a meal together. The number of people involved is manageable, and the steps for preparing the ingredients are simple. This being the case, it is not necessary for one person to be chosen to manage the overall process.
In a choreography saga, the microservices communicate directly with each other to execute the sub-transactions. Each microservice knows the tasks it is charged with performing and the context of the transaction. Communication usually takes place asynchronously via events or messages. Each microservice performs its tasks and triggers the relevant events to notify the next microservice in the sequence. For this to be possible, individual microservices must be able to coordinate in order to maintain the status of the transaction. There is no centralised point of control that monitors execution.
This type of saga is generally easy to implement and is well suited for short-lived transactions involving only a few steps where tracing is not required and there is no need to track the transaction status.
Conversely, if too many services are involved, it becomes increasingly difficult to identify where errors have occurred. At the same time, it is also not easy to know how many runtime dependencies there are and how to manage them.
The other type of saga is well suited for overcoming these challenges.
With saga orchestration, there is a central orchestrator that controls the execution of the sub-transactions. This is responsible for coordinating the microservices involved and managing the transaction status. The orchestrator ensures that the steps are carried out in the correct order and can initiate compensatory measures in the event of an error in order to restore the previous status. It acts as a central hub for controlling transactions and communication between the microservices.
The diagram above shows the order transaction presented earlier on, but this time as an orchestrator saga. The main difference is the use of a dedicated service that is responsible for orchestrating, tracking and tracing the necessary steps.
One key advantage of this type of saga is that cyclical dependencies are avoided, because the services do not communicate with each other but only with the orchestrator during the transaction. Another advantage is greater transparency, since the definition of the overall workflow is in one place where it can be adapted and tested.
However, this all comes at a high cost. The orchestrator becomes the single point of failure, meaning that, if it is unavailable or contains errors, the entire transaction cannot be executed, regardless of how reliable the other services involved are. Because implementation and maintenance are more complex, this type of saga is suitable for business transactions that involve many participating services (typically more than four) with long steps whose status needs to be tracked.
In our initial example from above, the orchestrator is the head chef who coordinates the kitchen stations at the restaurant. He gives each employee instructions on which ingredients to prepare and what order this must be done in. If there is a problem during one of the steps, he makes sure that everyone involved takes steps to ensure that the kitchen is in a good condition at the end of the process.
We have learnt about the saga pattern and the main features of it. We also looked at the most important types of sagas, these being choreography and orchestration. Both have their pros and cons, which must be weighed up against each other for every application. The number and length of the work steps as well as the need for status tracking are key things to consider when choosing which type of saga to use.
So the next time you are baking a cake or trying to execute a complex, distributed business transaction in a microservice architecture, think of the saga pattern as the secret ingredient for success.
You will find more exciting topics from the adesso world in our latest blog posts.