This repository presents a personal project focused on handling distributed transactions using the Orchestrated Saga Pattern. The goal is to build a robust microservices architecture capable of handling failures and maintaining data consistency without relying on the 2PC protocol.
Below are the main diagrams that illustrate the behavior of the system using the Orchestrated Saga Pattern and the interactions between the microservices involved:
Diagram showing the microservices, the saga orchestrator, and the databases involved, all connected through Apache Kafka.
This project implements a microservices architecture that simulates a complete flow of ordering, payment, and inventory update. Coordination between services is managed through the Orchestrated Saga Pattern, using asynchronous communication via Apache Kafka.
- Java 17
- Spring Boot 3
- Apache Kafka (event-driven communication)
- PostgreSQL (relational database)
- MongoDB (non-relational database for orders)
- Docker & docker-compose (containerized environment)
- Lombok, Spring Data, Spring Cloud Stream
The architecture is composed of 5 microservices:
- Manages the distributed transaction flow
- Controls the order of operations and executes compensating actions if a failure occurs
- Receives order creation requests
- Stores data in MongoDB
- Emits events to start the saga
- Processes payment attempts
- Performs compensation if needed
- Updates product stock
- Validates availability
- Compensates reservation in case of rollback
- Maintains product information
Represents the full flow when all steps in the transaction are completed successfully:
- Order is created
- Payment is authorized
- Inventory is updated
π docs/saga-success.png
Represents the compensating flow when a failure occurs at any step in the process, forcing the orchestrator to undo previous actions.
git clone https://github.com/RamonBecker/ms-saga.git
git clone https://github.com/RamonBecker/ms-saga.git
or install github https://desktop.github.com/
Before cloning the project, you will need to install docker on your operating system.
For windows, enter the following from the link:
https://docs.docker.com/desktop/windows/install/
For linux, follow the procedure below:
- Update your existing list of packages:
sudo apt update
- Install some prerequisite packages that let apt use packages over HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
- Add the GPG key to the official Docker repository on your system:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- Add the Docker repository to the APT sources:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
- Update the package database with Docker packages from the newly added repository:
sudo apt update
- Make sure you are about to install from the Docker repository instead of the default Ubuntu repository:
apt-cache policy docker-ce
- Install Docker:
sudo apt install docker-ce
- Check if it is working:
sudo systemctl status docker
- Once you have completed the docker installation, go to the infrastructure folder and run the following commands
docker compose up --build
docker compose up -d
- Asynchronous processing of distributed transactions
- Execution and orchestration of sagas with rollback
- Event-based communication using Apache Kafka
- Distributed data storage with PostgreSQL and MongoDB
- Docker containers for running the architecture locally
- Use of unique identifiers and idempotency control to avoid inconsistencies
Apache Kafka is a distributed event streaming platform used for asynchronous communication between microservices. In this project, Kafka acts as the message broker responsible for managing the events that trigger each stage of the Orchestrated Saga.
Kafka is used to:
- Publish events across services involved in the saga
- Decouple producers and consumers
- Enable reactivity and scalability in the orchestration
- Control rollback flows in failure scenarios
Kafka provides high performance, fault tolerance, partitioning, and event persistence, making it ideal for event-driven architectures.
- Orchestrated Saga: centralized transaction coordination
- Event-Driven Architecture (EDA): asynchronous service communication
- Outbox Pattern (planned): persistent and reliable event storage
- Idempotency: ensures operations are not duplicated
To better understand how the system works in practice, here is an example of a request and response for creating a new order via the Order API.
{
"products": [
{
"product": {
"code": "COMIC_BOOKS",
"unitValue": 15.50
},
"quantity": 3
},
{
"product": {
"code": "BOOKS",
"unitValue": 9.90
},
"quantity": 1
}
]
}{
"id": "64429e987a8b646915b3735f",
"products": [
{
"product": {
"code": "COMIC_BOOKS",
"unitValue": 15.5
},
"quantity": 3
},
{
"product": {
"code": "BOOKS",
"unitValue": 9.9
},
"quantity": 1
}
],
"createdAt": "2025-04-21T14:32:56.335943085",
"transactionId": "1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519"
}This response includes:
id: Unique identifier of the order stored in MongoDB.createdAt: Timestamp when the order was created.transactionId: Identifier used to track the distributed transaction across services (helps with idempotency and rollback).
This response confirms the order has been successfully created and that the orchestrator will manage the subsequent steps in the saga:
- Validate and process payment
- Reserve or update inventory
- Finalize or rollback depending on success or failure
The applications run on the following ports:
Order-Service: 3000Orchestrator-Service: 8080Product-Validation-Service: 8090Payment-Service: 8091Inventory-Service: 8092Apache Kafka: 9092Redpanda Console: 8081PostgreSQL (Product-DB): 5432PostgreSQL (Payment-DB): 5433PostgreSQL (Inventory-DB): 5434MongoDB (Order-DB): 27017
It is possible to retrieve saga data using either the orderId or the transactionId. Both queries return the same result.
GET http://localhost:3000/api/event?orderId=64429e987a8b646915b3735f
GET http://localhost:3000/api/event?transactionId=1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519By Ramon Becker ππ½ Get in touch!

