How Saga Pattern Handles Compensation Logic

Explore top LinkedIn content from expert professionals.

Summary

The saga pattern is a way to handle distributed transactions across microservices by breaking them into smaller steps, each with its own undo operation called compensation logic. Instead of relying on a single all-or-nothing transaction, sagas use compensating actions to keep data consistent when something fails along the way.

  • Design compensation steps: Make sure each business operation has a clear way to reverse its effects, such as refunding a payment or releasing reserved inventory, to maintain system consistency.
  • Choose coordination style: Decide between choreography, where services react to events, or orchestration, where a central controller manages the workflow, based on the complexity of your system.
  • Build for idempotency: Structure all compensation actions so they can be safely run multiple times without causing unwanted results like duplicate refunds or cancellations.
Summarized by AI based on LinkedIn member posts
  • View profile for Onkar Ojha
    Onkar Ojha Onkar Ojha is an Influencer

    SDE @Amazon || Ex - Jio || Linkedin Top-Voice

    13,865 followers

    🧩 Distributed Transactions in Microservices – The Hidden Nightmare Let’s say you're building an e-commerce platform. You’ve broken down your monolith into decoupled microservices: 🛒 Order Service (PostgreSQL) 📦 Inventory Service (MongoDB) 💰 Payment Service (MySQL) 🚚 Shipping Service (Cassandra) Each service manages its own database. Life is good... until it’s not. 😱 The Problem A user places an order. Here's what needs to happen: Order is created ✅ Inventory is reserved ✅ Payment is deducted ✅ Shipping is scheduled ❌ Suddenly, the Shipping Service fails maybe due to a timeout, a network error, or an unavailable carrier. Now what? You’ve already deducted payment and reserved inventory. There’s no easy way to rollback across multiple databases and services. Distributed transactions are not natively supported across microservices. Using 2-phase commits? Forget it's slow, complex, and breaks under scale. 🔄 Enter the SAGA Pattern SAGA solves this by breaking the transaction into a sequence of local transactions – each with a compensating action in case something fails. Let’s walk through the same scenario with SAGA: 🛒 Order Service creates the order → emits OrderCreated event 📦 Inventory Service reserves items → emits InventoryReserved or rolls back via ReleaseInventory 💰 Payment Service deducts amount → emits PaymentSuccessful or compensates via RefundPayment 🚚 Shipping Service fails to schedule → emits ShippingFailed → triggers compensating actions: •RefundPayment •ReleaseInventory •CancelOrder Each service maintains local state and knows how to undo its step if needed. 💡 Two Approaches: Choreography – Services listen to and act on domain events. Orchestration – A central orchestrator coordinates the flow. 🧱 SAGA DB Design Behind the Scenes In an orchestration-based saga: saga_instance → tracks the entire flow saga_step_log → logs each step’s status (SUCCESS / FAILED / COMPENSATED) Each microservice stores its part of the transaction locally (idempotency + recovery) ✅ Key Benefits No need for distributed transactions Works with independent databases Allows graceful rollback with compensation Keeps systems event-driven and loosely coupled

  • View profile for Elleuch Mohamed Yessin

    Software Engineer 🚀 | Back-End Developer 🧑💻 | java | Spring boot | Angular

    26,035 followers

    Saga Pattern Topic: Saga — Manage Distributed Transactions Without 2PC (Java + Spring Boot) Peak traffic. 10,000 orders per minute.Then the inventory service went down for 4 minutes. When it came back — we had a crisis. 😰 4,000 orders were in a state nobody could explain. Order Service said: CONFIRMED Payment Service said: CHARGED Inventory Service said: UNKNOWN 4,000 customers charged. No stock reserved. No way to know which ones.The support team was flooded. Refunds took 3 days to process manually.The root cause was painfully simple.We had no distributed transaction strategy. Our order flow was: 1. Save order → DB ✅ 2. Charge payment → Stripe ✅ 3. Reserve inventory → crashes ❌ Steps 1 and 2 completed. Step 3 never did. And we had no way to roll back steps 1 and 2. There's no BEGIN TRANSACTION across 3 microservices on 3 different databases. That's the fundamental problem of distributed systems. The fix was the Saga Pattern. Instead of trying to make 3 services atomic — we make each step reversible. Step 1: Create order ✅ Step 2: Charge payment ✅ Step 3: Reserve inventory ❌ (out of stock) → Compensate Step 2: Refund payment → Compensate Step 1: Cancel order → User sees: "Out of stock — you haven't been charged" java // Payment service reacts to OrderCreated @KafkaListener(topics = "order.created") public void onOrderCreated(OrderCreatedEvent event, Acknowledgment ack) { try { Payment p = paymentService.charge(event.getUserId(), event.getAmount()); kafka.send("payment.completed", new PaymentCompletedEvent(p)); } catch (PaymentFailedException ex) { // Compensation — tell Order Service to cancel kafka.send("order.cancel", new OrderCancelEvent(event.getOrderId(), ex.getMessage())); } ack.acknowledge(); } // When inventory fails — refund and cancel @KafkaListener(topics = "payment.refund") public void refundPayment(PaymentRefundEvent event, Acknowledgment ack) { paymentService.refund(event.getPaymentId(), event.getAmount()); // ← compensation kafka.send("order.cancel", new OrderCancelEvent(event.getOrderId())); ack.acknowledge(); } Two types of Saga — pick based on complexity 👇 🟣 Choreography — services react to each other's events. No coordinator. Loose coupling. Good for 2-3 steps. 🟠 Orchestration — a central Saga Orchestrator tells each service what to do. Easy to visualise. Good for complex flows. The two rules I follow without exception: 🔵 Compensations MUST be idempotent. If a refund is called twice — money is refunded once, not twice. 🟠 Always persist saga state. If the orchestrator crashes mid-saga, it needs to resume from where it left off — not start over. If a business operation spans 2+ services — it needs a Saga. There is no 2PC in microservices. #SystemDesign #Saga #Java #SpringBoot #Microservices #DistributedSystems #SoftwareArchitecture

  • View profile for Aman Sahni

    Java Full Stack Engineer | Building HungryCoders.com | 10+ Years of Experience

    45,648 followers

    If your payment succeeded but order creation failed, and you can't rollback across microservices - you need SAGA pattern. Imagine an e-commerce order flow across 3 services: -> Payment Service charges $100 -> Inventory Service reserves items -> Order Service creates order record Without SAGA: -> Payment succeeds -> Inventory fails (out of stock) -> Payment can't be rolled back (different DB) -> Customer charged but no order -> Manual refunds SAGA Pattern solves distributed transaction failures, below are the two SAGA Implementation Patterns: a) Orchestration -> Central coordinator manages the flow -> Easier to understand and debug -> Single point of failure -> Use when workflow is complex with many steps b) Choreography -> Services react to events using Kafka or RabbitMQ -> No central coordinator -> Better decoupling but harder to track -> Use when simple workflows in event-driven architecture Key SAGA Principles: a) Compensating Transactions: Every action must have an undo operation b) Idempotency: Same saga can be retried safely c) State Management: Track saga progress in database d) Eventual Consistency: Not ACID transactions Your distributed transactions need orchestration. #springboot #backend #hungrycoders

  • View profile for Naveen Reddy

    Building Roundz.ai - Community Driven Platform | SDE3 at Amazon

    11,023 followers

    Everything was working beautifully until an order needed to reserve inventory, charge payment, update loyalty points, and send confirmation. Service B decides to take a coffee break mid-transaction. Now you have reserved inventory, no payment, confused customers, and one very angry product manager staring at you. Welcome to distributed systems hell. This is exactly why the 𝗦𝗮𝗴𝗮 𝗽𝗮𝘁𝘁𝗲𝗿𝗻 exists. Instead of trying to coordinate everything in one massive transaction (spoiler: doesn't work), you break it into smaller, local transactions with a plan to undo everything if something fails. Think road trip with friends. Everyone drives their own car instead of cramming into one vehicle. If someone breaks down, they turn around without ruining everyone else's trip. Key takeaways from implementing sagas in production: • 🎭 𝗖𝗵𝗼𝗼𝘀𝗲 𝘆𝗼𝘂𝗿 𝗰𝗼𝗼𝗿𝗱𝗶𝗻𝗮𝘁𝗶𝗼𝗻 𝘀𝘁𝘆𝗹𝗲 𝘄𝗶𝘀𝗲𝗹𝘆 — Choreography (event-driven) scales better but debugging feels like following a crowded conversation. Orchestration (central coordinator) is easier to debug but creates bottlenecks. Start with orchestration for complex workflows, use choreography for simple chains. • ⚡ 𝗗𝗲𝘀𝗶𝗴𝗻 𝗰𝗼𝗺𝗽𝗲𝗻𝘀𝗮𝘁𝗶𝗼𝗻 𝗼𝗽𝗲𝗿𝗮𝘁𝗶𝗼𝗻𝘀 𝘂𝗽𝗳𝗿𝗼𝗻𝘁 — Every business operation needs a way to undo its effects semantically, not just technically. Releasing inventory isn't the same as never reserving it. Plan these compensating transactions as first-class business operations from day one. • 🔍 𝗜𝗻𝘃𝗲𝘀𝘁 𝗵𝗲𝗮𝘃𝗶𝗹𝘆 𝗶𝗻 𝗼𝗯𝘀𝗲𝗿𝘃𝗮𝗯𝗶𝗹𝗶𝘁𝘆 — Distributed tracing and correlation IDs aren't optional, they're survival tools. When a saga spans 5 services and fails at step 3, you need to trace exactly what happened and when across your entire system. • 🔄 𝗠𝗮𝗸𝗲 𝗲𝘃𝗲𝗿𝘆𝘁𝗵𝗶𝗻𝗴 𝗶𝗱𝗲𝗺𝗽𝗼𝘁𝗲𝗻𝘁 — Networks fail, services retry, compensation runs twice. Design every operation to be safely repeatable without side effects or you'll end up with duplicate refunds and very unhappy customers. The tradeoff? You get 𝗲𝘃𝗲𝗻𝘁𝘂𝗮𝗹 𝗰𝗼𝗻𝘀𝗶𝘀𝘁𝗲𝗻𝗰𝘆 instead of strict ACID transactions. Your system might look weird for milliseconds during execution, but it will either complete successfully or roll back completely. Ready to dive deeper into saga implementation patterns? Read the full breakdown at https://lnkd.in/gbsW7-sk or check out Roundz for interactive distributed systems practice problems. What's your experience with distributed transactions? Drop a comment below.

  • View profile for Vinothkumar P

    Senior Java Developer | Building Scalable, High-Performance Applications | Spring Boot | Microservices | Cloud.

    2,812 followers

     SAGA Design Pattern in Microservice Architecture -------------------------------------------------------- Saga is a design pattern used in microservices to manage long-running transactions. Saga is a design pattern used in microservices to manage distributed transactions. Instead of one global transaction, it breaks the process into a series of local transactions, each with a compensating action in case something fails. This allows the system to stay consistent using eventual consistency. Sagas can be implemented using choreography with events or orchestration with a central controller In a monolith, you’d use a database transaction: All steps succeed, or everything rolls back. But in microservices, that doesn’t work well because : ● Each service has its own database ● You can’t lock multiple databases in one transaction ● Calls are over the network → failures happen So instead of one big transaction, Saga uses: ➤ a sequence of local transactions, one per service ➤ with compensating actions to undo work if something fails Simple Example : ------------------- Imagine an Order system with 3 services: 1. Order Service – creates the order 2. Payment Service – charges the customer 3. Inventory Service – reserves items Normal flow : --------------- ● Order created ● Payment successful ● Inventory reserved → Order completed 🎉 Failure case : ---------------- ● Order created ● Payment successful ● Inventory fails ❌ Now what? Saga triggers compensating actions: ----------------------------------------- ● Refund the payment ● Cancel the order So the system stays consistent, even though there was no global transaction. Two Types of Saga -------------------- 1. Choreography-based Saga -------------------------------- ● No central controller ● Services communicate via events ● Each service listens and reacts Example : ---------- ● Order Service publishes OrderCreated ● Payment Service listens → processes payment → publishes PaymentCompleted ● Inventory Service listens → reserves stock Pros: ------ ● Loosely coupled ● Simple for small systems Cons: ------ ● Hard to understand flow ● Can turn into “event spaghetti” 2. Orchestration-based Saga ------------------------------- ● A central Saga Orchestrator controls the flow ● It tells each service what to do Example: ------------ ● Orchestrator → “Create order” ● Orchestrator → “Process payment” ● Orchestrator → “Reserve inventory” Pros: ------ ● Easier to track ● Clear business flow Cons: ------- ● Extra component ● Slightly tighter coupling When Should You Use Saga? ------------------------------ Use Saga when : ------------------ ● You’re using microservices ● You need data consistency ● Transactions span multiple services ● You can’t rely on distributed transactions (2PC) Do NOT use Saga : -------------------- ● In simple monolith apps ● When strong consistency is absolutely required instantly

  • View profile for sukhad anand

    Senior Software Engineer @Google | Techie007 | Opinions and views I post are my own

    105,764 followers

    Two phase commit in a microservice architecture is a bad idea. It’s too slow. It creates tight coupling. It blocks resources during prepare phase. So what do you do? The Saga Pattern 1. 2PC Blocking Problem Two-Phase Commit holds locks on all participants until the coordinator says commit. If the coordinator crashes, participants hold locks forever. System hangs. This is unacceptable in microservices. 2. Local Transactions Instead Break a distributed transaction into a sequence of local transactions. Each local transaction commits immediately and releases its lock. No global locking. No blocking. 3. Compensating Actions For every step, define a compensating action (undo). If Step 3 fails, execute the compensating actions for Step 2, then Step 1. Money is restored. System returns to a consistent state. 4. Choreography vs Orchestration Choreography: Events trigger the next step. No central coordinator. Harder to debug. Orchestration: A central Orchestrator directs the flow. Easier visibility. Centralized error handling. Orchestration is preferred for complex Sagas. 5. Eventual Consistency Saga does not provide immediate consistency. During execution, the system is in an inconsistent state. You must design for partial states (Money left A, not yet at B). 6. Idempotency and Retries Every step must be idempotent (safe to call twice). Every step must be retriable (safe to run after timeout). If the compensating action fails, you need a dead letter queue to handle it manually. 7. When to Use Saga Use Saga when transaction spans many services, throughput matters, and blocking is unacceptable. Do not use Saga if you need strong consistency and the logic cannot be reversed. Keep the core business logic in a monolith. Use Saga at the integration boundary. Are you using Sagas, or holding distributed locks for 10 minutes?

Explore categories