I talked about microservices at two conferences last week. In both opportunities, the attendees asked me about how to implement the Saga pattern. So, I decided to blog about it.
What is a Saga?
From the microservices.io:
A saga is a sequence of local transactions. Each local transaction updates the state (database) and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
The original idea is pretty old and comes from this article.
The implementation I recommend is known as “Orchestration-based saga.”

Saga as a Flow
I like to think Sagas as a long-running flow. Using BPMN (Business Process Modeling Notation), we could represent the preceding Saga as follows:

The good thing about representing Sagas as workflows is that we can run it using a workflow engine. So the workflow engine can act as the Saga Execution Coordinator.
What workflow engine I should/could use?
Like everything, the correct answer is: “It depends.” There are several options you could use. Some options are potent (and expensive). Also, there are a lot of lightweight and cheap alternatives. The right choice depends on your project.
I have been working (a lot) in a lightweight workflow engine library that you could use in your projects to solve a lot of problems (including “how to implement Sagas,” of course). It is still under development, but it will be ready to use soon.
Here is a preview of how you would configure your saga using my library:
var model = ProcessModel.Create()
.AddEventCatcher<CreateNewOrderCommand>("start")
.AddActivity<CreateOrderActivity>("CreateOrder")
.AddActivity<CancelOrderActitivity>("CancelOrder")
.AttachAsCompensationActivity("CancelOrder", "CreateOrder")
.AddActivity<CreateOrderActivity>("ReserveProducts")
.AddActivity<CancelOrderAcitivity>("CancelReservation")
.AttachAsCompensationActivity("ReserveProducts", "CancelReservation")
.AddActivity<RequestPaymentActivity>("RequestPayment")
.AddActivity<CancelPaymentActivity>("CancelPayment")
.AttachAsCompensationActivity("RequestPayment", "CancelPayment")
.AddActivity<RequestDeliveryActivity>("RequestDelivery")
.AddEventThrower("end")
.AddSequenceFlow("start",
"CreateOrder", "ReserveProducts",
"RequestPayment", "RequestDelivery",
"end"
);
var models = new InMemoryProcessModelsStore(model);
var instances = new InMemoryProcessInstancesStore();
var manager = new ProcessManager(models, instances);
Nice, huh?
Let me know if you are implementing microservices and need help. It would be a pleasure to help your company. Also, I would love to help you to start using my library (again, it is under development and source code is on Github).


