The Saga Pattern is a sequence of local transactions where each step updates the database and publishes an event or calls the next step. If one transaction fails, a compensation transaction is executed to undo the changes made by previous steps.
Real-world analogy: Booking a trip → flight, hotel, and payment services are involved. If the hotel booking fails, the flight reservation must be cancelled, and the payment refunded.
There are two common ways to implement Saga in microservices:
Each service produces and listens to events. There is no central controller.
Scenario: Order Service in E-Commerce
OrderCreatedEvent
is published.PaymentCompletedEvent
or PaymentFailedEvent
.
// Payment Service listening to OrderCreatedEvent
@EventListener
public void handle(OrderCreatedEvent event) {
if (processPayment(event.getOrderId())) {
eventPublisher.publish(new PaymentCompletedEvent(event.getOrderId()));
} else {
eventPublisher.publish(new PaymentFailedEvent(event.getOrderId()));
}
}
Pros: Decentralized, scalable, no single point of failure.
Cons: Harder to debug as system grows, risk of cyclic dependencies.
A dedicated Orchestrator Service controls the workflow, calling each service in sequence and triggering compensations on failure.
Scenario: Travel Booking
class BookingOrchestrator {
void bookTrip(String userId) {
try {
flightService.book(userId);
hotelService.reserve(userId);
paymentService.charge(userId);
} catch (Exception e) {
// Compensation logic
flightService.cancel(userId);
hotelService.cancel(userId);
paymentService.refund(userId);
}
}
}
Pros: Centralized control, easier monitoring and debugging.
Cons: Orchestrator may become a single point of failure.
The Saga Pattern is essential for building resilient microservices. Whether you choose Choreography or Orchestration depends on your system complexity:
Pro Tip: Always implement proper logging, monitoring, and compensation logic when applying Saga patterns to production systems.
0 Comments