Skip to content
System Designer

Go deeper · 7 minutes

Work across services

Make each step durable and show the user what is still pending.

Open this lesson
Make each step durable and show the user what is still pending.

Charged, but no order

Checkout calls inventory, then payments, then delivery. The payment succeeds just as the order service crashes. A retry cannot tell whether to charge again. There is no single database transaction across these services. The business needs a durable story for each intermediate state, including an unknown result.

Choose the transaction boundary

Choose a step to fail, then run the saga. Undo completed effects in reverse order. A compensation is a new action that can need its own retries.

Worked example: one durable order

Commit the order, crash before publishing, then restart. Compare a durable outbox intent with a direct publish. Repeated delivery must still deduplicate at the consumer.

Bound the unfinished work

A broker acknowledgement does not prove an order shipped. Persist saga state, use stable operation keys for both effects and compensations, retry with jitter and alert on the age of pending work. Each consumer needs local atomicity and deduplication. Show received, awaiting payment, confirmed, refund pending and refunded states. Set a deadline and a support path for work that automation cannot settle.

Bound unfinished work

  • 30-minute outage: 200 orders/s accumulate 360,000 orders. At 2 KB each, that is about 720 MB.
  • Recover: 300/s net: 500/s processing − 200/s new arrivals = 300/s of backlog drain.
  • 20-minute catch-up: 360,000 / 300 = 1,200 seconds. Set a deadline and a support path for unresolved work.

Key numbers

Outage backlog
≈ 360,000 orders. 200/s × 1,800 s
Workflow payload
≈ 720 MB. 360,000 × 2 KB; before indexes and replicas
Catch-up
≈ 20 minutes. 360,000 ÷ (500 - 200)/s

Check your reasoning

Think through these questions before opening the lesson. In the game you can test the idea and compare your reasoning.

  • An outbox relay publishes, then crashes before marking the row sent. What protects a consumer's local effect on replay?
  • Why not use two-phase commit for checkout? Follow-up: are sagas equally atomic?
  • Checkout times out while calling a provider that may have accepted the charge. What should it do?
  • Where exactly is the idempotency key stored? Follow-up: the worker crashes between checking the key and applying the change.
  • Workers handle 250/s while arrivals stay at 300/s. No work expires or is shed. What happens to the backlog?

The key point

Commit locally, publish through an outbox, and make every later effect safe to repeat or reconcile.

Practise this idea

Continue through the lesson tracks