Skip to main content

Command Palette

Search for a command to run...

Saga Pattern - Architecture guide

Published
5 min read
Saga Pattern - Architecture guide

Microservices driven architecture is getting increasingly common. Microservices are small independent services that do one thing and one thing right with very clear API boundaries. A complex system is built by using multiple microservices calling each other. I think of this as lego bricks being used to build a more complex object.

This approach allows for better people management. Small teams can work on their independent code base without worrying too much about other teams. This reduces need to synchronize with other teams and communication overhead.

The disadvantages of microservices is that it might leads to inefficient allocation of compute power, increase RPC communication overhead and debugging might become harder as bug in one system might propagate to other callers.

Saga Pattern

In this post we are going to discuss the architectural pattern called “Saga”. Saga in english means a long story of heroic achievement. Modern businesses using technology are often like this. Long chain of multiple events leading to different things. For example user searching for flight tickets and then choosing one, booking one, doing payment, later cancelling the flight etc.

Saga pattern inherently is designed for such complex scenarios to break them down into smaller pieces and help design small self contained microservices.

In user’s perspective this is a single journey they are taking. In system’s perspective this is one of the possible paths.

A typical travel website supports millions of searches per day but only thousands of tickets get booked each day. Out of those thousands few hundred will eventually get cancelled. So the scalability needs for each of these steps are very different.

Similarly, there are different reasons to send out mails to the customer. Booking emails, payment emails, changes to flight itinerary emails etc.

To make sense of these steps there are two subtypes.

Choreographed Saga

This phrase comes from the world of dance. A dance is a series of steps that each participants take. Every dancer does their own moves and trusts the partner to do their moves. There is no centralized co-ordinator forcing them to make specific moves. It is all determined by convention.

In microservices Choreographed Saga is designed as each micro-service doing its work and reporting its results in a particular communication channel. If the micro-service fails to do its job it reports the failure as well. Any other micro-service that depends on this has to be responsible for taking steps depending on the success or failure result.

For example Booking system might record user’s desire to book a ticket. Hold the ticket and ask user to complete the payment. The payment system reports success or failure result on the channel that booking system is responsible for listening and take next steps accordingly. The failure path handling is often called “compensatory actions”.

Here Booking system asks payment system to process a payment and respond on the reply channel. If the payment system fails to process the payment the booking system will remove the ticket hold. If the payment succeeds then booking system will mark the ticket as sold.

What if the payment succeeds but Booking system fails to mark the ticket as bought ? The booking system is then responsible for issuing a refund request to the payment system.

How the payment system handles payment or refunds, what emails it might send to the user etc. is not determined by Booking system. It only sees the payment system as two micro-service calls. “ProcessPayment” and “RefundPayment”.

Similarly, Payment system does not care at all about why the payment is being made. It only does two things it is being asked to do.

This reduces complexity and makes thing much simpler to engineer.

Pros:

  1. Good scalability as there are no centralized systems.

  2. Development and testing can be independently done.

Cons:

  1. Changes to communication protocol is harder.

  2. Bugs can have a domino effect.

  3. Communication design is complex.

Conductor Saga

This phrase comes from the world of music where a conductor instructs everyone on what to do. This conductor is a centralized broker who knows all the steps and their logic and is responsible for actions. This makes it easier for engineers to code the logic of flows in a single system.

In this system broker tells Booking to hold a ticket and it asks the payment to process a payment. Booking system does not know about the existence of Payment system. The broker will check the results of payment and ask booking to do whatever that needs to be done. Broker will also decide what email communication needs to be sent out.

Conductor pattern is useful in cases where the communication logic might be changing often and is far too critical to be left to distributed systems to implement correctly.

Pros:

  1. You have all the flow logic at single place

  2. Debugging is easier

  3. Bug detection is easier

Cons:

  1. Conductor is a single point of failure

  2. Conductor code gets complex with time

  3. Scalability has challenges

Why use Saga at all ?

Nearly all modern highly scalable systems end up using Saga pattern in some form for at least some of their problems. Saga’s benefits are that you do not have to rely on any long held locks. You can scale or rearchitect each system independently while keeping them loosely coupled.

Modern business needs are often a good justification as businesses often are run as complex long running processes involving multiple events.

To give you more context we have a deep dive into Saga pattern here.