Ace8 is the modernization practice of AceMQ.24/7 support from AceMQ after go-live
Book an Assessment

Guide

Saga pattern: keeping data consistent after you split the monolith.

Inside a monolith one database transaction covers the whole checkout. Once you split, it does not. This is how teams replace it.

AceMQ engineering team4 min readEngineer-reviewed

The short answer

The saga pattern replaces one distributed transaction with a sequence of local transactions. Each step commits in its own service and triggers the next. If a step fails, earlier steps are undone by compensating actions. Sagas give eventual consistency across services without locking databases together.

01The problem

Why does splitting a monolith break your transactions?

Take a checkout. In the monolith, one @Transactional method reserves stock, charges the card and creates the order. If the charge fails, the database rolls everything back.

Split those three into services with their own databases and that rollback is gone. Two-phase commit across services is possible, but it ties availability together and most teams avoid it. This is usually where monolith to microservices projects find out that the schedule risk sits in the data, not the code.

02How it works

What a saga does, step by step

The idea is old. Garcia-Molina and Salem described sagas for long-lived database transactions in 1987.

  1. 01

    Order service creates the order in a pending state and commits locally.

  2. 02

    Inventory service reserves stock and commits locally.

  3. 03

    Payment service charges the card. Suppose this fails.

  4. 04

    The saga runs compensations in reverse: inventory releases the stock, order service marks the order cancelled.

  5. 05

    Every service ends in a consistent state. For a short time, the system was visibly in between.

Planning this for your estate? Get a fixed scope and price first.

03Choose a style

Choreography or orchestration?

There are two ways to coordinate the steps. The rule of thumb: choreography for three or fewer participants, orchestration beyond that or when the flow has branches.

ChoreographyOrchestration
Who drives the flowEach service reacts to events from the lastA central coordinator tells each service what to do
Where the flow livesSpread across servicesIn one place you can read
CouplingServices know the events, not each otherServices know the coordinator's commands
DebuggingHard: you trace events across logsEasier: the coordinator holds saga state
Best forShort, linear flows with few participantsLonger flows, branches, timeouts, human steps
Main riskHidden cyclic dependencies between servicesCoordinator becomes a bottleneck or a god service

04Design rules

How do you design compensating transactions?

A compensation is a business action, not a database rollback. Design it with these rules.

  • Idempotent. The coordinator may send a compensation twice. Running it twice must be safe.
  • Semantic. Refund the payment, do not delete the payment row. Audit trails need the original.
  • Retriable. Compensations must eventually succeed, so retry them. Do not design one that can fail permanently.
  • Ordered by pivot. Steps before the pivot point can be compensated. Steps after it are retried forward until they succeed.
  • Visible state. Use states such as PENDING and CANCELLED so other readers know the data is not final.

05Reliable messaging

Where does the outbox pattern fit?

Each step must do two things together: update its own database and publish a message. If the service crashes between the two, the saga stalls or a step runs twice.

The transactional outbox fixes this. The service writes the business change and an outbox row in the same local transaction. A separate relay then reads the outbox table, by polling or through change data capture such as Debezium, and publishes to the broker. Delivery is at least once, so consumers must be idempotent: store the message ID and skip repeats.

06Do you need one

When you do not need a saga

Sagas also come with tooling choices, such as workflow engines (Temporal, Camunda), the Axon framework, or hand-written state machines. Pick the tool after you have drawn the steps and compensations on paper.

  • The two pieces of data can stay in one service and one database. Keep them together.
  • You are building a modular monolith first. Modules share a transaction, so there is nothing to compensate yet.
  • The workflow tolerates a manual fix. A weekly reconciliation job is cheaper than a saga for rare, low-value cases.

07How Ace8 helps

How Ace8 helps find the transactions before they break

Ace8 is the AI-assisted application modernization practice of AceMQ. During a split we scan for every transaction boundary that crosses a proposed service edge, and flag which ones need a saga, which can move into one service, and which can be redesigned.

That list is part of the modernization assessment, and it feeds the plan on the monolith to microservices page.

FAQ

Frequently asked.

Something else on your mind? Ask an engineer.

A way to keep data consistent across services by running a sequence of local transactions, with compensating actions that undo earlier steps if a later one fails.

Start here

Know the cost before anything moves.

A fixed-price assessment gives you the inventory, the risk score and a phased plan. Scope and cost are fixed before the migration starts.

Get in touch

Talk to a modernization engineer

Tell us what you run today. An engineer, not a sales script, replies within one business day.

305-204-2607info@ace8.io

66 W. Flagler St. 9th Floor
Miami, FL 33130

What are you moving off? *

Fixed price. Scope and cost before any migration starts.