Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
All Blog Reports
([Link] ([Link] ([Link]
papers)
Return to Microservices list ([Link]
Saga Pattern Microservices Tutorial:
Using the Saga Pattern with Spring
Boot & RabbitMQ
By Onkar Musale In Microservices Posted June 12, 2025
Search here
Latest Posts Popular Posts
8 Key Benefits of Mobile Devices in Hea
([Link]
devices-in-healthcare)
React Native Maps Tutorial: Master Inte
Distributed transactions across microservices require a different approach than the traditional Google Maps with React Native
([Link]
two phase commit (2PC). In a Spring Boot microservices architecture, where each service
development/react-native-maps-intera
owns its own database and communicates over the network, 2PC becomes complex, slow, and google-maps-tutorial)
error prone due to tight coupling and potential locking across services.
AI Traffic Explodes 357%, Tesla Robots
To address this, the Saga pattern in microservices has become a widely adopted solution. Startup That’s Actually Making Gold
([Link]
Instead of one global transaction, a Saga breaks the workflow into a series of local
in-the-loop-ai-and-tech/ai-traffic-tes
transactions, each managed by an individual service. Once a service completes its part, it
publishes an event (e.g., “DebitCompleted”), which other services consume to trigger their Scaling Mobile Engagement with Flutter
own local operations. Smarter Navigation in Apps
([Link]
development/flutter-deep-linking-guid
This event driven architecture in Spring Boot creates a loosely coupled, scalable system where
each step in the process knows just enough to do its job. If all goes well, the saga flows through AI Heats Up: Nvidia’s China Comeback,
each service to completion. The $1.8 billion Swedish Unicorn
([Link]
But real systems aren’t perfect; failures happen. If any service fails during the process, the in-the-loop-ai-and-tech/ai-heats-up-
agent-swedish-unicorn)
Saga pattern allows you to run compensating transactions, custom logic designed to undo the
effects of previously completed steps. For example, if a credit operation fails, the debit service The Ultimate Guide to Using Chatbots fo
can be asked to roll back the money transfer. Customer Support
([Link]
retail/chatbots-for-ecommerce-suppor
This way, eventual consistency is preserved without distributed locks or tight coordination,
making it ideal for resilient, fault tolerant microservices. This is particularly effective when
paired with robust cloud development services ([Link]
[Link] Page 1 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
development?utm_source=blog&utm_medium=internal_link&utm_campaign=saga-pattern-
spring-boot_blog&utm_content=cloud-development) to support scalability and on demand
infrastructure.
TAGS
Follow this Saga pattern microservices tutorial step by step with me, and implement it in your
asynchronous messaging
IDE to fully understand the Saga pattern and how to apply it in your projects. By the end, you’ll ([Link]
be confident in setting up and managing distributed transactions in Spring Boot using the Saga messaging)
pattern.
compensating transactions
In this tutorial, we will build a simple money transfer microservice system consisting of: ([Link]
transactions)
Account-Debit Service (runs on port 8081)
Account-Credit Service (runs on port 8082) distributed systems reliability
([Link]
systems-reliability)
Both services will communicate solely via RabbitMQ microservice communication (using Spring
AMQP), without any REST calls between them. We will use in-memory data and expose REST
endpoints for testing with Postman: distributed transaction spring boot
([Link]
transaction-spring-boot)
Debit Service:
POST /transfer → publishes a TransferRequested event
event driven architecture spring boot
GET /accounts → view in-memory balances ([Link]
driven-architecture-spring-boot)
Credit Service:
GET /accounts → view in-memory balances eventual consistency
([Link]
consistency)
The Saga Workflow:
fault-tolerant microservices
([Link]
Debit Service consumes TransferRequested →
tolerant-microservices)
If there is sufficient balance, debit the “fromAccount”, then publish DebitCompleted;
Otherwise, publish DebitFailed. idempotency in microservices
([Link]
Credit Service consumes DebitCompleted → in-microservices)
If credit logic succeeds, credit the “toAccount”, then publish CreditCompleted;
microservices coordination
Otherwise, publish CreditFailed. ([Link]
coordination)
Debit Service also listens for CreditFailed →
Issue a compensation refund (i.e., add back the amount to “fromAccount”).
rabbitmq microservice communication
([Link]
We’ll implement full AMQP (Advanced Message Queuing Protocol) RabbitMQ saga microservice-communication)
implementation, event DTOs, AccountStore (in memory balances with all methods),
@RabbitListener handlers, and REST controllers. Finally, we’ll run RabbitMQ locally via Docker rabbitmq saga implementation
and test the entire flow with Postman, including a simulated credit failure. This implementation ([Link]
saga-implementation)
can complement more advanced devops services
([Link]
utm_source=blog&utm_medium=internal_link&utm_campaign=saga-pattern-spring- saga pattern example spring boot
([Link]
boot_blog&utm_content=devops) for streamlined automation, testing, and deployment.
pattern-example-spring-boot)
saga pattern microservices
([Link]
pattern-microservices)
service orchestration vs choreography
[Link] Page 2 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
([Link]
orchestration-vs-choreography)
spring boot microservices architecture
([Link]
boot-microservices-architecture)
spring boot money transfer microservice
([Link]
boot-money-transfer-microservice)
spring boot saga pattern
([Link]
boot-saga-pattern)
([Link]
utm_source=blog&utm_medium=cta_button_link&utm_campaign=saga-pattern-spring-
spring microservices transaction manag
boot_blog&utm_content=software-development-company ) ([Link]
microservices-transaction-managemen
Technologies
Java 17
Spring Boot 4.0.0
Spring AMQP (spring-boot-starter-amqp)
RabbitMQ (Docker image: rabbitmq:3-management)
Postman (or any REST client)
Project Setup
Open Spring Initializer ([Link] generate two services, Debit Service and
Credit Service, then download the generated ZIP files. Extract and import each service as a
Maven project into your preferred IDE.
Add the following dependencies to your project:
Spring Web – for building RESTful APIs
Spring for RabbitMQ – for asynchronous messaging support using AMQP
Spring Boot DevTools – for automatic restarts and live reload during development
To see how this kind of setup scales and aligns with modern software practices, check out our
in-depth CI/CD with Docker & AWS Blog ([Link]
with-docker-and-aws?utm_source=blog&utm_medium=internal_link&utm_campaign=saga-
pattern-spring-boot_blog&utm_content=ci-cd-with-docker-and-aws) for integrating
continuous deployment in similar microservice architectures.
[Link] Page 3 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
1. Running RabbitMQ Locally via Docker
Use Docker to run RabbitMQ:
docker run -d --hostname rabbit --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
AMQP port: 5672
Visit Management UI: [Link] ([Link] (default user/pass:
guest / guest)
Management Home Page:
[Link] Page 4 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
2. Common Event DTOs
Each microservice defines its own copy of the following DTO classes. This design supports
microservices coordination and ensures modularity within a distributed system. For each DTO,
ensure that it includes: a constructor with all fields, appropriate getters and setters, and an
overridden toString() method.
Debit Service → [Link]
public class TransferRequested implements Serializable {
private String transferId;
private String fromAccount;
private String toAccount;
private Double amount;
private TransferRequested() {}
}
public class DebitCompleted implements Serializable {
private String transferId;
private String fromAccount;
private String toAccount;
private Double amount;
private DebitCompleted() {}
}
public class DebitFailed implements Serializable {
private String transferId;
private String reason;
private DebitFailed() {}
}
public class CreditFailed implements Serializable {
private String transferId;
private String reason;
private Double refundAmount;
private String refundAccount;
private CreditFailed() {}
}
Credit Service → [Link]
[Link] Page 5 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
public class DebitCompleted implements Serializable {
private String transferId;
private String fromAccount;
private String toAccount;
private Double amount;
private DebitCompleted() {}
}
public class CreditCompleted implements Serializable {
private String transferId;
private String toAccount;
private Double amount;
private CreditCompleted() {}
}
public class CreditFailed implements Serializable {
private String transferId;
private String reason;
private Double refundAmount;
private String refundAccount;
private CreditFailed() {}
}
3. AccountStore Component (Both Services)
We simulate accounts in-memory. Place this class in debit service under
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@Component
public class AccountStore {
private final Map<String, Double> accounts = new ConcurrentHashMap<>([Link]("A", 100.0, "B", 50.0));
public Map<String, Double> getAccounts() {
return accounts;
}
public Double getBalance(String acct) {
return [Link](acct, 0.0);
}
public void updateBalance(String acct, Double newBal) {
[Link](acct, newBal);
}
public boolean debit(String acct, Double amount) {
synchronized (accounts) {
Double balance = getBalance(acct);
if (balance >= amount) {
Double updated = balance - amount;
updateBalance(acct, updated);
return true;
} else {
return false;
}
}
}
public void credit(String acct, Double amount) {
synchronized (accounts) {
Double balance = getBalance(acct);
Double updated = balance + amount;
updateBalance(acct, updated);
}
}
}
Explanation
We use a ConcurrentHashMap to store balances for accounts “A” and “B” by default.
Because we’re not using a real database, this is purely in-memory; all state resets when
the services restart.
Methods:
[Link] Page 6 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
getAccounts(): returns the map for GET /accounts endpoint.
getBalance(String): returns current balance or 0.
updateBalance(String, Double): overwrites balance.
debit(String, Double): synchronized check and subtract; logs each step.
credit(String, Double): synchronized add; logs each step.
This idempotency in microservices is crucial to avoid duplicate transactions in event driven
architecture systems.
4. Spring Boot + RabbitMQ Configuration (AMQP)
RabbitMQ is a message broker that uses the AMQP protocol (Advanced Message Queuing
Protocol) to send and receive messages between different systems in a reliable and
asynchronous manner.
Spring Boot makes it easy to integrate RabbitMQ using the Spring AMQP module. It abstracts
the low-level AMQP details, enabling seamless RabbitMQ microservice communication with
simple annotations and configurations.
You use @RabbitListener to receive messages from a queue.
You use [Link]() to send messages to an exchange with a
routing key.
Spring handles message serialization, deserialization, connection management, retries,
and error handling under the hood.
Together, Spring Boot and RabbitMQ provide a clean and efficient way to enable event-driven
communication between microservices or components in a distributed system.
This idempotency in microservices is crucial to avoid duplicate transactions in event-driven
architecture systems. For additional reading on building resilient systems with messaging
queues and distributed services, refer to our guide on Spring Boot with Apache Kafka
([Link]
utm_source=blog&utm_medium=internal_link&utm_campaign=saga-pattern-spring-
boot_blog&utm_content=spring-boot-apache-kafka-guide).
Exchange, Routing Keys and Queues Configurations:
We configure a single Direct Exchange named [Link], plus five queues:
[Link]
[Link]
[Link]
[Link]
[Link]
Bindings route messages by routing key, e.g. “[Link]” →
[Link], “[Link]” → [Link], etc.
[Link] Page 7 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
5. Debit Service Implementation (Port 8081)
Debit-service package structure
5.1 [Link] (Debit Service)
[Link]=debit-service
[Link]=8081
[Link]=localhost
[Link]=5672
[Link]=guest
[Link]=guest
5.2 [Link]
[Link] Page 8 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class DebitServiceApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
5.3 [Link]
Add the AccountStore class from the above given example for debit service.
5.4 [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].Jackson2JsonMessageConverter;
import [Link];
import [Link];
import [Link];
@Configuration
public class RabbitMQConfig {
public static final String EXCHANGE = "[Link]";
public static final String QUEUE_TRANSFER_REQUESTED = "[Link]";
public static final String QUEUE_DEBIT_COMPLETED = "[Link]";
public static final String QUEUE_DEBIT_FAILED = "[Link]";
public static final String QUEUE_CREDIT_COMPLETED = "[Link]";
public static final String QUEUE_CREDIT_FAILED = "[Link]";
public static final String RK_TRANSFER_REQUESTED = "[Link]";
public static final String RK_DEBIT_COMPLETED = "[Link]";
public static final String RK_DEBIT_FAILED = "[Link]";
public static final String RK_CREDIT_COMPLETED = "[Link]";
public static final String RK_CREDIT_FAILED = "[Link]";
@Bean
DirectExchange sagaExchange() {
return new DirectExchange(EXCHANGE);
}
@Bean
Queue transferRequestedQueue() {
return [Link](QUEUE_TRANSFER_REQUESTED).build();
}
@Bean
Queue debitCompletedQueue() {
return [Link](QUEUE_DEBIT_COMPLETED).build();
}
@Bean
Queue debitFailedQueue() {
return [Link](QUEUE_DEBIT_FAILED).build();
}
@Bean
Queue creditCompletedQueue() {
return [Link](QUEUE_CREDIT_COMPLETED).build();
}
@Bean
Queue creditFailedQueue() {
[Link] Page 9 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
return [Link](QUEUE_CREDIT_FAILED).build();
}
@Bean
Binding bindTransferRequested(Queue transferRequestedQueue, DirectExchange exchange) {
return [Link](transferRequestedQueue).to(exchange).with(RK_TRANSFER_REQUESTED);
}
@Bean
Binding bindDebitCompleted(Queue debitCompletedQueue, DirectExchange exchange) {
return [Link](debitCompletedQueue).to(exchange).with(RK_DEBIT_COMPLETED);
}
@Bean
Binding bindDebitFailed(Queue debitFailedQueue, DirectExchange exchange) {
return [Link](debitFailedQueue).to(exchange).with(RK_DEBIT_FAILED);
}
@Bean
Binding bindCreditCompleted(Queue creditCompletedQueue, DirectExchange exchange) {
return [Link](creditCompletedQueue).to(exchange).with(RK_CREDIT_COMPLETED);
}
@Bean
Binding bindCreditFailed(Queue creditFailedQueue, DirectExchange exchange) {
return [Link](creditFailedQueue).to(exchange).with(RK_CREDIT_FAILED);
}
@Bean
MessageConverter converter() {
return new Jackson2JsonMessageConverter();
}
@Bean
AmqpTemplate amqpTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
[Link](converter());
return rabbitTemplate;
}
}
5.5 [Link]
[Link] Page 10 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Component
public class DebitEventHandler {
private final RabbitTemplate rabbitTemplate;
private final AccountStore accountStore;
public DebitEventHandler(RabbitTemplate rabbitTemplate, AccountStore accountStore) {
[Link] = rabbitTemplate;
[Link] = accountStore;
}
@RabbitListener(queues = RabbitMQConfig.QUEUE_TRANSFER_REQUESTED)
public void handleTransferRequest(TransferRequested request) {
boolean success = [Link]([Link](), [Link]());
if (success) {
DebitCompleted event = new DebitCompleted([Link](), [Link](),
[Link](), [Link]());
[Link]([Link], RabbitMQConfig.RK_DEBIT_COMPLETED, event);
} else {
DebitFailed event = new DebitFailed([Link](),
"Insufficient balance in account: " + [Link]());
[Link]([Link], RabbitMQConfig.RK_DEBIT_FAILED, event);
}
}
@RabbitListener(queues = RabbitMQConfig.QUEUE_CREDIT_FAILED)
public void handleCreditFailed(CreditFailed event) {
[Link]([Link](), [Link]());
}
}
5.6 [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
@RequestMapping("/transfer")
public class TransferController {
private final RabbitTemplate rabbitTemplate;
public TransferController(RabbitTemplate rabbitTemplate) {
[Link] = rabbitTemplate;
}
@PostMapping
public String requestTransfer(@RequestBody TransferRequested request) {
[Link]([Link], RabbitMQConfig.RK_TRANSFER_REQUESTED, request);
return "Transfer requested: " + [Link]();
}
}
5.7 [Link]
[Link] Page 11 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
@RequestMapping("/accounts")
public class BalanceController {
private final AccountStore accountStore;
public BalanceController(AccountStore accountStore) {
[Link] = accountStore;
}
@GetMapping
public Map<String, Double> getAccounts() {
return [Link]();
}
}
6. Credit Service Implementation (Port 8082)
Credit-service package structure
*PackageExplorerX ⽇g9
vcredit-service[boot][devtools]
vsrc/main/java
v#[Link]
>[Link]
v##[Link]
>[Link]
v#[Link]
>[Link]
[Link]
>[Link]
>[Link]
>[Link]
v@[Link]
>[Link]
v#[Link]
>[Link]
v#sic/main/resources
&static
Btemplates
[Link]
>Esic/test/java
>BAJRESystemLibrary[JavaSE-17]|
>alMavenDependencies
>asrc
atarget
[Link]
mvnw
[Link]
м[Link] MOBISOFT
›•debit-service[boot][devtools]
6.1 [Link] (Credit Service)
[Link]=credit-service
[Link]=8082
[Link]=localhost
[Link]=5672
[Link]=guest
[Link]=guest
6.2 [Link]
[Link] Page 12 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class CreditServiceApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
6.3 [Link] (Credit Service)
package [Link];
import [Link];
import [Link];
import [Link];
@Component
public class AccountStore {
private final Map<String, Double> accounts = new ConcurrentHashMap<>([Link]("C", 20.0, "D", 80.0));
public Map<String, Double> getAccounts() {
return accounts;
}
public Double getBalance(String acct) {
return [Link](acct, 0.0);
}
public void updateBalance(String acct, Double newBal) {
[Link](acct, newBal);
}
public boolean debit(String acct, Double amount) {
synchronized (accounts) {
Double balance = getBalance(acct);
if (balance >= amount) {
Double updated = balance - amount;
updateBalance(acct, updated);
return true;
} else {
return false;
}
}
}
public void credit(String acct, Double amount) {
synchronized (accounts) {
Double balance = getBalance(acct);
Double updated = balance + amount;
updateBalance(acct, updated);
}
}
}
6.4 [Link] (Credit Service)
Use the same exchange and queue names as the Debit Service, so that they share the same
RabbitMQ infrastructure.
6.5 [Link]
[Link] Page 13 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Component
public class CreditEventHandler {
private final RabbitTemplate rabbitTemplate;
private final AccountStore accountStore;
public CreditEventHandler(RabbitTemplate rabbitTemplate, AccountStore accountStore){
[Link] = rabbitTemplate;
[Link] = accountStore;
}
@RabbitListener(queues = RabbitMQConfig.QUEUE_DEBIT_COMPLETED)
public void handleDebitCompleted(DebitCompleted event) {
// Simulate a failure for a specific transferId "FAIL-CREDIT"
if ("FAIL-CREDIT".equals([Link]())) {
CreditFailed cf = new CreditFailed([Link](), "Simulated credit failure", [Link](),
[Link]());
[Link]([Link], RabbitMQConfig.RK_CREDIT_FAILED, cf);
return;
}
[Link]([Link](), [Link]());
CreditCompleted cc = new CreditCompleted([Link](), [Link](), [Link]());
[Link]([Link], RabbitMQConfig.RK_CREDIT_COMPLETED, cc);
}
}
6.6 [Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
@RequestMapping("/accounts")
public class BalanceController {
private final AccountStore accountStore;
public BalanceController(AccountStore accountStore) {
[Link] = accountStore;
}
@GetMapping
public Map<String, Double> getAccounts() {
return [Link]();
}
}
7. Testing the Saga Flow via Postman
To validate the spring boot money transfer microservice, start both the Debit and Credit
services. Ensure each service runs on its assigned port and is connected to the RabbitMQ
server (typically on port 5672)..
7.1 Debit Service Accounts:
[Link] Page 14 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Check the /accounts endpoints of each service to view the current account balances. The Debit
Service contains two accounts, A and B with balances { “A”: 100.0, “B”: 50.0 }, while the
Credit Service includes accounts C and D with balances { “C”: 20.0, “D”: 80.0 }.
GET [Link]
7.2 Credit Service Accounts:
GET [Link]
7.3 Perform Successful Transfer
To simulate a successful money transfer, initiate:
POST [Link]
[Link] Page 15 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Working:
Debit Service receives a TransferRequested with transferId=TXN1001.
[Link](“A”, 30.0) → succeeds (100.0 ≥ 30.0). A’s new balance = 70.0.
Publishes DebitCompleted(“TXN1001″,”A”,”C”,30.0).
Verify Debit Service Account Balances:
GET [Link] → {“A”:70.0,”B”:50.0}
Credit Service consumes DebitCompleted:
Does not match “FAIL-CREDIT”, so [Link](“C”, 30.0) → C’s new
balance = 50.0.
Publishes CreditCompleted(“TXN1001″,”A”,30.0).
Verify Credit Service Account Balances:
GET [Link] → {“C”:50.0,”D”:80.0}
[Link] Page 16 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
7.4 Insufficient Funds (Debit Failure)
To simulate failure in debit:
POST [Link]
Reach Out To
Us
What Happens:
Your full name*
Debit Service tries [Link](“A”,1000.0) → fails (70.0 < 1000.0).
Publishes DebitFailed(“TXN1002″,”Insufficient balance…”). Your email address*
Credit Service does not react to DebitFailed (no listener).
Phone number
Balances remain unchanged. (optional)
India
Verify:
How can we help you?
Debit Service:
GET [Link] → {“A”:70.0,”B”:50.0} By submitting this form,
you explicitly agree to
Mobisoft Infotech Privacy
Credit Service remains the same.
Policy
([Link]
7.5 Simulated Credit Failure (Compensation) policy) and Terms of
Service
[Link] Page 17 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
To simulate a credit failure and trigger the saga pattern compensation: ([Link]
of-services).
POST [Link]
REACH OUT
TO US
Working:
Debit Service:
[Link](“A”,20.0) → succeeds (A’s balance = 50.0).
Publishes DebitCompleted(“FAIL-CREDIT”,”A”,20.0).
Credit Service receives DebitCompleted(“FAIL-CREDIT”,…):
Matches “FAIL-CREDIT” → publishes CreditFailed(“FAIL-CREDIT”, “Simulated
credit failure”).
Debit Service listens for CreditFailed:
[Link](“A”,50.0) (compensation refund). A’s balance goes back to
100.0 (50.0 + 50.0).
Verify:
Debit Service:
GET [Link] → {“A”:100.0,”B”:50.0}
[Link] Page 18 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Credit Service remains unchanged.
State of RabbitMQ Exchanges and Queues on Management Portal
8. Conclusion & Next Steps
We’ve successfully built a Spring Boot money transfer microservice using the Saga pattern that
demonstrates:
RabbitMQ (AMQP) for asynchronous messaging
@RabbitListener for consuming events
AccountStore for in memory balances
REST APIs for testing with Postman:
POST /transfer (Debit Service)
GET /accounts (both services)
Next Steps:
Use a database: Persist accounts and saga state for production.
Docker Compose: Combine both services and RabbitMQ into one [Link].
Unit tests: Write tests for each handler using @SpringBootTest and mocks.
Security: Add authentication/authorization to REST endpoints.
[Link] Page 19 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Wrapping Up:
We’ve successfully implemented a distributed transaction system using the Saga pattern. Now
you can extend this pattern for more complex workflows and scale it for production. Keep
experimenting with advanced features like fault tolerance and resilience, and don’t forget to
secure your services for a complete, production ready solution.
If you’re looking to build scalable microservices or distributed systems, explore our end-to-
end software development services ([Link]
development-company?utm_source=blog&utm_medium=internal_link&utm_campaign=saga-
pattern-spring-boot_blog&utm_content=software-development-company) tailored for
modern enterprise needs. You can explore the complete source code on our GitHub
([Link] repository.
([Link]
utm_source=blog&utm_medium=cta_button_link&utm_campaign=saga-pattern-spring-
boot_blog&utm_content=contact-us )
Author's Bio
Onkar Musale is a Senior Software Engineer at Mobisoft Infotech
([Link]
utm_source=blog&utm_medium=internal_link&utm_campaign=saga-
pattern-spring-boot_blog&utm_content=home-page) with over 6.5
years of experience in Java backend development and cloud
Onkar Musale technologies, I specialize in designing scalable microservices and robust
RESTful APIs using Java Spring Boot and Golang. I’m passionate about
leveraging AWS, Docker, and Kubernetes to build high-performance,
cost-efficient solutions. My expertise spans database management
(MySQL, PostgreSQL, MongoDB), API documentation, payment gateway
integrations, and advanced cloud configurations. I’m a quick learner,
resilient, and always eager to adapt to new technologies, dedicated to
delivering quality solutions that drive business success.
([Link]
[Link] Page 20 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Name
Let's Stay Business Email
Connected By submitting this form, you explicitly agree to Mobisoft Infotech
Privacy Policy ([Link] and
Get our latest posts delivered right to your inbox. Terms of Service ([Link]
SUBSCRIBE
Insights
Have a glimpse of our insightful blogs on exciting topics.
Resilience4j Circuit Breaker Tutorial Saga Pattern Microservices Tutorial:
along with Retry & Bulkhead patterns Using the Saga Pattern with Spring
for Spring Boot Microservices Boot & RabbitMQ
([Link]
([Link]
circuit-breaker-retry-bulkhead-spring-boot) pattern-spring-boot-rabbitmq-tutorial)
View All Posts (/resources/blog)
Contact us
Submit the form to schedule a meeting and discover how we can assist you
[Link] Page 21 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Call us
Your full name*
USA +1-855-572-2777([Link]
IND +91-858-600-8627([Link]
Your email address*
Book a ([Link]
meeting us)
India
Business inquiry
business@[Link]
Phone number (optional) ([Link]
General information
info@[Link]
How can we help you? ([Link]
Career with us
jobs@[Link]
([Link]
Locations
By submitting this form, you explicitly agree to
USA
Mobisoft Infotech
Privacy ([Link] 5718, Westheimer Rd Suite
Policy policy) 1000 Houston, TX 77057
and
Terms of ([Link] INDIA
Service of-services) Level 2, Trident Business Center,
. Opposite Audi Showroom, Baner, Pune -
411045
Submit
Services Solutions Industries Business Inquiry
AI Enablement & Consulting Data Engineering Retail & E-commerce +1-855-572-2777 (USA)
Transportation &
([Link]
([Link]
Logistics (/industry/retail- ([Link]
intelligence) engineering-services) ecommerce-solutions)
Retail & E-Commerce +91-858-600-8627
Digital Product Engineering UX/UI Design Logistics & Transportation
(India)
([Link]
([Link] (/industry/transportation-
product-engineering-services)ux-design) logistics) ([Link]
Healthcare
Product Discovery Test Automation Sports & Entertainment business@[Link]
([Link]
([Link] (/industry/digital- ([Link]
discovery-software-solutions) automation) Others transformation-sports-
entertainment)
Custom Software Development RPA
([Link]
([Link] Healthcare
development-company) process-automation-services) (/industry/healthcare- Mobisoft Infotech
digital-transformation) About (/about-us)
Digital Transformation Digital Commerce
([Link]
([Link] High Tech & Startups Our Approach (/our-
transformation-services) commerce) (/startup-it-solutions- approach)
services)
Software Sustenance Team Augmentation Partners (/software-
([Link]
([Link] development-partners)
maintenance-and-support) augmentation)
Tech Stack (/technology-
Mobile App Development Cybersecurity Consulting ([Link] stack)
([Link]
app-development-company) Careers (/jobs-at-
mobisoft)
[Link] Page 22 of 23
Saga Pattern with Spring Boot & RabbitMQ Tutorial 29/07/25, 10:41 PM
Cloud Services HIPAA Consulting Blog (/resources/blog)
([Link]
([Link]
development) consulting-services) Engagement Models
(/engagement-models)
Web Development Salesforce Consulting
([Link]
([Link] Contact (/contact-us)
web-development-company) consulting)
Cyber Fraud & Scam Alert
DevOps Services Startup Consulting (/cyber-scams-misusing-
([Link]
([Link] mobisoft-infotech-name)
it-solutions-services)
IoT Services
([Link]
Shopify Consulting
development-services) ([Link]
IT Consulting
([Link]
consulting-company)
USA (Houston, Texas) ([Link]
([Link]
([Link]
([Link]
([Link]
([Link]
([Link]
([Link]
([Link]
INDIA (Pune, Maharashtra) ([Link] Infotech/131035500270720)
infotech)
Privacy Policy (/privacy-policy)
([Link]
Terms of Services (/terms-of-services)
Sitemap (/sitemap-mi)
TOP
MOBILE APP
DEVELOPERS
SelectedFirms
© 2025 Mobisoft Infotech
R
TOP IT
SERVICE COMPANY
INDIA
[Link]
Certified Member 2021
[Link] Page 23 of 23