DEV Community

Saga Pattern Made Easy

Emily Fortuna on May 24, 2023

This is part 2 of a series. To read about compensating actions, check out Compensating Actions, Part of a Complete Breakfast with Sagas. ...
Collapse
 
michaeltharrington profile image
Michael Tharrington

Thanks so much for sharing your post here, Emily!

Really appreciated your humor throughout and the resource links + notes at the end. Awesome writing on an interesting topic! 🙌

Collapse
 
emily_fortuna profile image
Emily Fortuna

Thank you, @michaeltharrington!

Collapse
 
siy profile image
Sergiy Yevtushenko

Saga pattern is specific to microservices rather than distributed systems in general. Microservices is one of those primitive distributed systems which do not maintain consensus. This results in inability to perform any tasks which require coordination between several nodes.

Implementation of Saga pattern ought to be done at business logic level and each type of transaction must be implemented separately. Each implementation is fragile and error prone. Mixing business logic and Saga steps makes code hard to read, understand, support and maintain. Finally, Saga pattern does not provide any kind of isolation between transactions. This may result in subtle, hard to nail down and fix bugs. Those bugs may cause data loss or corruption.

Collapse
 
emily_fortuna profile image
Emily Fortuna

Aren't steps of your Saga business logic in some form? How do you propose to separate them?

Collapse
 
siy profile image
Sergiy Yevtushenko

Usually they describe states of some business entities, for example orders. Such states usually modelled as dedicated fields in those business entities. Such an approach allows easy handling of transitions using traditional generic transaction mechanisms. But this option assumes shared data, which is a big "no" for microservices.

Thread Thread
 
emily_fortuna profile image
Emily Fortuna

Ah, got it. You're arguing this is an issue with the saga pattern itself. It's definitely not always the first choice. 2 phase commit is "cleaner", but there are cases where 2PC is not possible (throughput is more important, and 2PC has the possibility to hang)

Thread Thread
 
siy profile image
Sergiy Yevtushenko • Edited

You've missed whole point: distributed transaction in microservices is the problem, not a particular way to perform them. Microservices by design, intentionally reduce coupling between nodes (services) down to the level, where coordination necessary to perform distributed transaction is impossible. Moreover, in properly designed microservices-based system they should be unnecessary, as microservice governs all necessary data and can use regular (and not distributed) transaction mechanisms.
I think that initial idea of microservices was understood incorrectly and this results in all sorts of issues. Handling connectivity issues and transactions at business logic level are among ugliest ones as they screw up design and result in fragile and error prone implementation. But if we return to the original idea, everything gets natural and does not cause issues mentioned above:

  • no distributed transactions and no fragile logic which needs to be created on case-per-case base (saga) or handled across unreliable nodes (2PC) at business logic level
  • connectivity issues are natural part the business logic in this case. It's sort of browser - web site situation: when we're typing URL in browser or clicking link at page, we're expecting that this operation may fail for various reasons, including connectivity. Retrying and/or postponing request also part of business logic in this case.

If we still need distributed transactions because domain is too big to fit into one service, we just need to use design approaches which support them. There is nothing wrong with that (quite the opposite), but technically those approaches are not microservices and should not be treated as such. For example, requirement to govern all data for EDA components (which usually also called "services") is not applicable to them. They are by design tightly coupled via reliable data storage - streaming/queuing or pub-sub infrastructure.

In other words, each type of design has its own area of application and problem arises when they are used incorrectly. And main cause of improper choice of design - incorrect selection of domain boundaries. We're so focused on technical side that forget that domain is defined by business. And vast majority of businesses have only one domain. Only large and very large organizations usually are big enough to have more than one domain. Such companies are rare enough and therefore microservices should be rare too.

I've made a more detailed article dedicated to the issue.

Collapse
 
adophilus profile image
Adophilus • Edited

I'm too dumb to understand this 😭. I'll try reading it again