Sagas — Part 1: An Introduction
Sagas — Part 1: An Introduction
Sagas — Part 2: Sagas in Distributed System
Sagas — Part 2b: Sagas in Distributed Systems Continued
Sagas — Part 3: Choreography Instead?
Sagas — Part4: Design Considerations
A Microservice does not exist in a vacuum, and sooner or later, to achieve anything meaningful, microservices will have to interact with each other. These interactions can vary, but I want to discuss Sagas in this post.
I have seen a few places where Sagas are used to describe choreographed interactions, not just orchestrated ones. I personally always thought of Sagas as orchestrators, and this stems from my understanding of the original intention of Sagas and the problems they tried to solve. So from here on, when I use Sagas, I’m talking about orchestrators or orchestration-based Sagas as I have seen them being referred to.
What is an orchestrator? An orchestrator coordinates a business process involving two or more services through commands. It generally reacts to events and sends commands. Commands can be synchronous or asynchronous, depending on the required guarantees. An orchestrator is often centralised and hence represents a single point of failure — I say “often” as there are ways to implement orchestrators in a non-centralised way — Routing Slips are an example.
In previous posts, I have detailed my preference for choreography as it creates loosely coupled services and eliminates the need for a centralised coordinator. I have even worked at places where the fascination with choreography led to an organisation-wide architecture rule dictating that it should be the only way to model interactions between services. So why do we need orchestration?
The problem with choreography is that, in my opinion, it does not work as well when the process is complex or is likely to change frequently. The decentralised nature of choreography means the overarching process is scattered across multiple services, making it harder to determine what the process involves — without resorting to documentation or monitoring tools. If the process requires changing, then it’s likely that several services must be altered and deployed at the same time, increasing the risk of making changes.
Orchestrators provide better visualisation of the business process as it’s centralised, so you need only look in one place for the entire process. Additionally, if you want to change the process itself, you can discard the old process and create a new one without having to change any of the services participating in the process. The alterations are contained within the orchestrator, minimising the risk of changing it.
Sagas were created to deal with LLTs or long-lived transactions by breaking those into microtransactions, each with a compensating action.
A LLT is a saga if it can be written as a sequence of transactions that can be interleaved with other transactions. The database management system guarantees that either all the transactions in a saga are successfully completed or compensating transactions are run to amend a partial execution
Hector Garcia-Molina and Kenneth Salem (https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf)
Sagas are used in distributed systems to tackle transactions across service boundaries instead of classic two-phase commit, distributed transactions. Distributed transactions raise several issues when implemented across services, as in order to preserve ACID properties, we may need to lock resources in the multiple data stores of the participant services. But services ought to be autonomous; hence, we cannot enforce how long a transaction must take. Locking resources for a more extended period can lead to deadlocks.
Sagas attempt to break down the overarching transaction into multiple, independent and reversible local transaction - one per participating service. They are attempted sequentially, and if one fails, all completed ones are reverted. This will be the topic of the next post in this series.