# Consistency Without Distributed Transactions — Monolith vs Microservices

Source: https://www.skillbyai.com/en/monolith-microservices/r-consistency

> Keep data consistent across services with sagas, outbox and idempotency.

## Giving up the single transaction

In a monolith, placing an order, reserving stock and recording payment can be one ACID transaction. Across services with separate databases, that is gone. **Two-phase commit** across services is rarely used in practice: it couples availability and is poorly supported by modern datastores and brokers. Instead, use a **saga**: a sequence of local transactions, each in one service, with **compensating actions** to undo earlier steps on failure (release stock, refund payment). Sagas can be **choreographed** through events or **orchestrated** by a coordinator or workflow engine. Publish events reliably with the **transactional outbox**, and make consumers **idempotent**, because messages can arrive more than once. Design the user experience for **eventual consistency**: "Order received" first, then "Order confirmed". The Event-Driven Architecture course covers these patterns in depth.

## A saga instead of one transaction

Local transactions run step by step; a failure triggers compensations in reverse.

![A row of three step boxes connected by forward arrows, with a dashed set of backward arrows underneath representing compensations.](assets/figures/monolith-microservices/section-6-map.svg) — Figure 6.1 — Forward steps and compensating actions in a saga.

## Steps and compensations for checkout

Each forward step has a defined undo; compensations must be idempotent.

```text
step                         service      compensation
---------------------------  -----------  ---------------------------
1 create order (PENDING)     orders       mark order CANCELLED
2 reserve stock              inventory    release reservation
3 authorise payment          payments     void authorisation / refund
4 confirm order              orders       (last step, nothing after it)

failure at step 3 -> run compensations for 2, then 1
all steps and compensations: idempotent, keyed by orderId
```

## Compensations are business decisions

"Undo" is not always possible: an email cannot be unsent and a parcel may already be shipped. Agree with the business what compensation means for each step, such as a follow-up email or a return label.

**Quiz:** What replaces a cross-service ACID transaction in most microservice systems?

- [ ] A shared database lock
- [ ] Two-phase commit across every service
- [x] A saga of local transactions with compensating actions
- [ ] Running all services in one process

*Answer:* A saga of local transactions with compensating actions. Sagas keep each step local and undo completed steps with compensations on failure.
