Guest post originally published on Mia-Platform’s blog by Francesco Francomano, Senior Full Stack Developer, and Giuseppe Manzi, Full Stack Specialist at Mia-Plarform.

In the context of microservices, one of the problems that we often encounter is the need to guarantee data consistency, updated in parallel by different actors. 

In this case, the Saga architectural pattern is becoming popular: let’s find out how it works and which problems it solves. 

Data Consistency: what is it and which problems does it imply?

Guaranteeing data consistency means ensuring that data is significantly and efficiently usable in the company’s applications. 

An example of data consistency comes from an e-commerce website: after the payment of an order, it is necessary to update both the payments tables and the order tables, to ensure that the order is paid and that it can be shipped. These updates potentially come from different sources and must preserve data coherence. 

Securing data consistency is a sensitive subject. 

Particularly, there are two points of attention that should be taken into account in these kinds of situations: 

In order to secure the consistency of data is fundamental to ensure that the execution flow of the different operations on diverse microservices respect a certain order. This implies guaranteeing error safety, that is the presence of a remediation mechanism which restores the right situation in case of a mistake. 

To give a concrete example, let’s analyze a modern food service delivery: the operations that “carry on” an order are multiple and often involve different actors, each of which executes one or more operations, as the use case below. 

It is not always easy, with all the steps and actors listed above, to guarantee data consistency in all the points and to avoid mistakes along this chain. 

This is where a data management pattern, that is becoming more and more popular as a preferred response in this kind of situation, comes to help: the Saga Pattern.

What is the Saga Pattern?

The idea behind the Saga Pattern, as described in the previous paragraph, is the management of distributed transactions, from start to finish, each of which is, indeed, a saga.

This is a pattern whose purpose is to ensure the execution order of transactions that are part of one saga, or that must be performed in a predetermined order and whose effect is not compromised by any intermediate transactions belonging to different sagas.

Therefore, this pattern helps to manage the consistency of data in the execution of distributed transactions among various microservices. It involves different actors (services) that go to act on the same entity through individual transactions aimed at updating a common data.

The goal is twofold: to maintain the identity of data and carry out compensation actions to restore it in the event of an error.

Comparison of different approaches to Saga Pattern

There are mainly two approaches to manage the pattern under consideration:

Both of the above approaches have pros and cons, and clearly, there is not a universal rule that establishes whether one approach should be used rather than the other: it always depends on the project to be implemented.

Events/choreography approach

The events/choreography approach establishes that all microservices involved work triggered by specific events, like proper choreography. 

There isn’t a coordinator that manages everything, but every service knows what to do and when to do it. As a matter of fact, the union of the work of each service enables to start, progress and finish the saga. 

This collaboration occurs through the exchange of messages – events – among microservices, usually with a Message Broker.

In this way, we have a decentralized logic, distributed among the various services that deal with the saga.

Taking up the previous example of the food delivery order system, the choreography of events could be as follows:

As you can see in the use case above, each service knows exactly its environment, what to do and when to do it. The saga progresses naturally despite the fact that it involves different microservices, which one does a different thing: they do not need to communicate directly, despite carrying out a sequence of activities indirectly linked to each other.

This approach has several advantages:

However, it also has some disadvantages:

Commands/Orchestration Approach

This approach, unlike the previous one, involves the use of a central service that manages and controls the entire flow of the saga. The service is, as the name of the approach suggests, the orchestrator.

The orchestrator has the role of controller and all the actors involved in the transaction interface with it.

According to this approach, the orchestrator directs the flow, sending commands to each service in the form of messages through the Message Broker. Upon receiving this command, the service implements its own logic to carry on the saga and responds by sending an event via the Message Broker, which will be managed by the orchestrator.

In this way, the orchestrator will be able to carry on the saga by directing its “orchestra” of services.

The previous example of the order on a food delivery system could be, this time, the following:

Also in this case, the services know their environment only and implement that small part of the logic linked to the saga. However, this time they have a sort of reference point, as can be seen in the following diagram.

Mia Platform Saga pattern diagram

The advantages of this approach: 

Mia Platform Saga pattern diagram

The disadvantages are the following:

Which approach would you choose?

In the previous chapter, we described the pros and cons of both the events/choreography and commands/orchestration approaches. Which one to choose obviously depends on the specific case.

For example, it could be disadvantageous to develop an orchestrator to manage a saga that involves two microservices and a very simple flow: the added value obtained from the introduction of an orchestrator would be canceled out by a considerable increase in complexity, especially at the beginning, linked to the commands/orchestrator approach.

Which approach we chose

As mentioned, at Mia-Platform we had to face this problem and, consequently, we had to choose which approach best suited our case. Before talking about the chosen approach, however, it is important to briefly introduce the variables that influenced and determined our choice.

Following the initial analysis of the project, we designed a rather complex finite-state machine, which represented exactly all the possible saga flows, that are all the ways in which it could have evolved.

Starting from this automaton, we have identified the various steps of the saga flow and the designated actors – the microservices – to carry on the saga.

At this point there were two approaches available:

Several factors and needs influenced the choice:

Given the aforementioned requirements, the choice was simple. We opted for the Commands/Orchestration approach and, since we didn’t find on the web ready-to-use implementations of an orchestrator, we decided to enrich the platform by developing a new component: the Flow Manager.

Read this article to learn more about Flow Manager, the saga orchestrator of Mia-Platform.