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.
- 01
Order service creates the order in a pending state and commits locally.
- 02
Inventory service reserves stock and commits locally.
- 03
Payment service charges the card. Suppose this fails.
- 04
The saga runs compensations in reverse: inventory releases the stock, order service marks the order cancelled.
- 05
Every service ends in a consistent state. For a short time, the system was visibly in between.
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.
| Choreography | Orchestration | |
|---|---|---|
| Who drives the flow | Each service reacts to events from the last | A central coordinator tells each service what to do |
| Where the flow lives | Spread across services | In one place you can read |
| Coupling | Services know the events, not each other | Services know the coordinator's commands |
| Debugging | Hard: you trace events across logs | Easier: the coordinator holds saga state |
| Best for | Short, linear flows with few participants | Longer flows, branches, timeouts, human steps |
| Main risk | Hidden cyclic dependencies between services | Coordinator 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.