Orchestration based Saga Pattern for microservices with Camunda

Satyam Pushkar
6 min readJan 30, 2022

This article showcases how to implement Orchestration based Saga pattern for microservices using Camunda with sample dotnet code. You can find the sample code used in this article here.

Photo by Omar Flores on Unsplash

Microservices is no more a buzz word for developers & architects. Many a times in microservice world a single requests processing may need communication across multiple services. In this type of distributed system, each service might have it’s own database. Then how to keep the data consistent across the request?

Saga pattern is the answer to keep the data consistent in microservices in distributed transactions. These are the transactions which spanned across multiple microservices. These transactions run successfully till the end or if something fails it rollbacks completely. This way it runs on a principle of either all or none at all and this makes data consistent across microservices. Please check the example shown in below image.

From creating order to delivering order, all gets executed one after another to complete the successful transaction. But if something fails, for example delivering order or updating inventory, a set of transactions runs to nullify/cancel the whole transaction which started at creating order. These transactions(Cancel Order, Reverse Payment, Reverse Inventory, Cancel Delivery) are known as compensatory transactions which undo the changes done by preceding transactions.

There are 2 ways to implement saga pattern:

  1. Choreography: In choreography a local transaction publishes a domain event which triggers local transaction in other services.
  2. Orchestration: In orchestration, there will be a centralized controller which tells the participants which local transactions to execute.

In this article I have explained the orchestration based saga design pattern. There are both pros and cons of saga. Based on the use case one should decide whether to use it or not. Orchestration is a good option for complex workflows which includes multiple steps. It is also a very good option for evolving and changing business processes. It avoids cyclic dependencies and creates a clear separation of concerns. But it adds additional design complexity to implement coordination logic and also adds a probable single point of failure.

Instead of creating the orchestrator on my own, I have used Camunda as the orchestrator. Netflix uses Conductor and Uber uses Cadence for orchestration of workflows which are implemented across the distributed system of their microservices. Camunda is an open source framework for business workflow and process automation. To know more about it please check out this article.

Demo application

To showcase saga orchestration through an example, I have created four sample microservices: order, payment, inventory and delivery. All these microservices are minimal web API created using dotnet. You can run all of them separately or run on Docker environment. For demo purpose I have used docker-compose to run microservices (I have used Docker desktop for the same). You can find the services and docker-compose(yaml file) here.

  • This is a very simple application where all these four services are performing their domain specific operations.
  • Then Camunda engine is used to perform the orchestration.
  • There is another dotnet based API: camunda-helper which has implemented all the handlers which are used by Camunda to perform the operations. These handlers in turn call the respective (domain specific) microservices. In Camunda we can define the process using BPMN which simplifies creating business process very easy. To know more about it please check these articles by me: Camunda basics part1 & part2.

The above image shows the BPMN diagram which shows a transaction starting from creating to delivering the order. The whole transaction constitutes of four local transactions and each has one compensatory transaction. Either the given order gets processed successfully or it gets reverted and gets cancelled keeping the local databases consistent.

Steps to run the application:

  • Run the ‘docker-compose.yml present under ‘camunda.demo.process/ms-saga-demo/’ to start all the microservices instances.
  • You can run all of them on local machine too. (Check the port number which is exposed and use the same in ‘camunda-helper’ API solution).
  • Run the camunda-helper API which opens the swagger page.
  • Choose the option ‘Process_Transaction_Saga_Orchestrator’ to start the process (This mimics that one order has came for processing). To demonstrate the capabilities, I am throwing exceptions from all the local transactions (which is randomly generated based on no 1 to 4). You need to run the process multiple times to see different flows.

You can see the below screen shot of running all the domain specific microservices. Before starting to test, you need to add items to inventory. You can use the script ‘Add-Items-to-Inventory.ps1’ to add some products to inventory. Optionally you can use swagger/postman also.

After you choose the ‘Process_Transaction_Saga_Orchestrator’ option after running the ‘camunda-helper’ solution, you will find different results (because of exceptions raised based on random numbers). As you can find in the left side image 2 instances: 1st one (blue colored) of successful transaction and 2nd one (red colored) is where error occurred while updating inventory. And hence the compensating transactions (reverse inventory, reverse payment and cancel order) got executed to keep the data consistent(keep the data as it was before the transaction).

This was a very simple use case but we can tweak it out based on our condition to add retry or checkpoints to complete the transaction if it reaches a certain point or return otherwise. Camunda makes it very easy to design all these workflow orchestrations. You can try to fit it based on your requirement.

This was a sample use case showing how to implement orchestration based saga pattern for microservices using Camunda. Hope you find this article useful. To know basics of Camunda please check these articles by me: Camunda basics part1 & part2 .

For further reading on Saga pattern you can check out https://microservices.io/patterns/data/saga.html and https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/saga/saga .

You can also read these articles to know more about Camunda based Saga pattern implementation https://blog.bernd-ruecker.com/saga-how-to-implement-complex-business-transactions-without-two-phase-commit-e00aa41a1b1b or https://tkssharma.com/Event-driven-architecture-using-camunda-Microservice-workflow-orchestration/ .

Please do checkout other articles by me and share your feedback(s) if any. Thank you and Happy Coding :)

--

--

Satyam Pushkar

Software Engineer | Backend Specialist | System Architect | Cloud Native Apps | DOTNET, PYTHON | https://www.linkedin.com/in/satyampushkar/