Saga Pattern for Distributed Transactions

If you have been following the course, you may have noticed that most transactions occur within a single domain in the complete architecture of our system.

But what happens if we need to act across multiple domains? This is where the saga pattern comes into play.

 

 

1 - What is the saga pattern?

The saga pattern is a pattern we use to ensure consistency in our transactions when they include multiple microservices, and we achieve this through events.

In a monolithic world, this would mean updating multiple tables within a transaction, but of course, this is not possible in distributed systems.

 

We can use SAGA patterns created manually with producers/consumers or as "all in the same application" by relying on an external library. This always depends on our use case and on the structure we have.

 

The main point of the pattern is that we must create service structures for scenarios where everything works well, and for other scenarios where actions fail.

 

For example, continuing with the Distribt course, we have creating an order, which requires different steps:

steps to create an orderWe can see different parts of the process where everything works well; each one could be from a different microservice or the same.

And now we have to include all the cases where something fails, which is where things start to get a bit complicated.

order creation with failures

As we can see, we have different scenarios if something fails. In some cases, we want to roll back, such as product validation. In others we want to retry, in others we need a manual action. This action is called compensation.

 

 

2 - Designing a saga

As we have just seen, a SAGA consists of a series of transactions that are tightly coupled to each other and complete a process or a flow from beginning to end.

 

These transactions contain the happy path when everything works well and a part called compensation, which happens when something fails.

The important thing here is that we should not leave events or the process half-done. Therefore, in our case, we are going to turn our previous diagram into a SAGA flow:

order creation saga

As we can see, the process that in a monolith would be inserting data into three tables has become much more complicated. And this flow is reduced, because we could add more steps to make it perfect.

 

For every step forward we take, we have to have at least one prepared to go back, but more likely, there are two or even more, since either we have to undo what was changed, or we need to alert someone to perform a manual action and unblock the process, and so on.

 

Additionally, as you can see, we are using a service bus, which in our case will be RabbitMQ. It does not matter which one we use, what is important is that we must use the producer/consumer pattern no matter what, so everything needs to be very well designed and thought out.

 

2.1 - Designing a saga in .NET

When building a SAGA in your system, you simply need to follow all the guidelines and steps. But, as you might imagine, this is quite complex, since we have to create handlers for each event, in addition to having everything well configured.

 

This process works for any programming language; it is completely language-independent. But in .NET we have a series of libraries that allow us to create Sagas in an easier way.

In this group we can find libraries like MassTransit, Microsoft Orleans, Rebus, and many others.

saga pattern c#

In the case of MassTransit or Rebus, all the communication is based on the producer/consumer pattern via RabbitMQ. Meanwhile, Microsoft Orleans is more focused on API calls. All these libraries maintain saga state information so if something does not work correctly, it continues from that point. Let’s say the library is responsible for ensuring that everything is executed, and nothing is left half-done.

 

Professionally, aside from implementing the distributed saga manually with handlers (my favorite approach), I have used MassTransit in projects where it was already introduced.

And Microsoft Orleans was used during a migration from a monolith that was highly entwined within its domains to microservices. The migration was done little by little and the system was not prepared to switch to the producer/consumer pattern efficiently during that transition. Once the migration was finished, we removed Orleans as all sagas were then implemented "manually."

 

 

Conclusion

In this post, we have seen what the saga pattern is.

How the saga pattern differs from a transaction in a monolith.

How to design a SAGA.

How to create SAGAs in C#.

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café