Getty Images

How the saga design pattern in microservices works

When a sequence of steps must be performed to support an operation, the microservices saga design pattern is a perfect fit.

The saga design pattern is a style of software architecture that's intended to manage distributed tasks that execute as a sequence of steps in a failsafe manner. The saga design pattern is well-suited to a microservices-oriented architecture.

By definition, services in an MOA are discrete and self-contained, and each microservice carries its own logic and data.

Any data sharing between microservices must be implicit, usually by way of a messaging framework. In the saga pattern, each step corresponds to a particular microservice. The overall benefit of a saga pattern is that it keeps track of the steps in a sequence and addresses issues that arise in a formal manner.

A distinguishing characteristic of the saga pattern is a compensation. This behavior executes when something goes wrong in a step and the overall workflow must revert to the last known good state.

Because each step in a saga pattern is well-encapsulated, a general practice among developers is to create a dedicated compensation for each step in the saga. Sometimes the compensation is external and associated with the given step of a saga; other times the compensation is embedded directly in the service that implements a given step's behavior.

When to use a saga design pattern

The saga pattern is well-suited for business workflows that must reset in their entirety if there is a failure in any one of the workflow's steps. Order processing workflows and supply chain management systems are typical use cases.

For example, imagine a travel agent that makes airline, hotel and car rental reservations for a customer's trip. The agent must abide by a governing rule: If any of the reservations fail, all the reservations made hitherto must be canceled as if the trip never happened. So, if the sequence of reservations is airline, hotel and car rental, a failure in the car rental reservation means the reservations for airline and hotel must be canceled too. If the hotel reservation fails, the airline reservation must be canceled and the car rental reservation must not happen at all.

Get the code

This article has an accompanying repository on GitHub with TypeScript code that demonstrates both the orchestration and choreography styles of implementing the saga design pattern.

Orchestration vs. choreography

There are two approaches to implement a saga: orchestration and choreography. Let's dig deeper into each approach.

Saga design and orchestration

In an orchestrated saga, a central controller manages the steps and compensations within a sequence. If the first step is successful, the controller proceeds to run the next step in the sequence. If there is a problem running the step, the controller executes the compensation for the failing step. If the failure occurs downstream after a few steps, the sequence terminates and the controller runs the compensation for the failing step plus the compensations for all the previous steps.

Figure 1 illustrates the orchestrated approach used to implement the travel agent example described above. You can also view and run a concrete code example that implements the orchestration approach in the GitHub repository dedicated to this article.

Visual showing the saga design pattern and orchestration
Figure 1. Implementing the saga design pattern using orchestration.

Sage design and choreography

In the choreographed approach to a saga design pattern, each step acts independently with no central controller. One step knows its subsequent step in the process, so when it completes it calls the next step. If a call fails, the called step executes its compensation and then throws an error. The calling step catches the error and executes its compensation, and all the previous steps execute their own compensations in a reversed cascade.

Figure 2 below illustrates a choreographed version of the travel agent saga pattern described above. You can view and run the code here in the same GitHub repository.

Visual showing the choreography of microservices across sagas
Figure 2. Implementing the saga design pattern using choreography.

One distinction between these two approaches to a saga design is that the choreographed approach can be hard to maintain. In an orchestrated approach the sequence of steps is apparent in the controller, but in a choreographed approach the next step in the saga is hidden within the code of each step. Thus, to make changes a developer must do a bit of detective work to figure out the overall sequence.

On the other hand, the saga design pattern is very compatible with other design patterns such as the actor model that are based on independent, well-encapsulated services working together.

Putting it all together

There's a lot of commercial software development activity involved with programming business workflows. It's hard to run a business in modern times without them. Nevertheless, despite their importance, these workflows can be very difficult to create and even harder to maintain.

The saga design pattern provides a blueprint for developers that makes these efforts a lot easier. It's still a significant undertaking to create a useful business workflow in code, but it's nowhere as hard as starting from scratch.

Bob Reselman is a software developer, system architect and writer. His expertise ranges from software development technologies to techniques and culture.

Dig Deeper on Front-end, back-end and middle-tier frameworks