A distributed transaction (2PC) is not an option.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # ======================================================================
# Q: Order, stock and payment are in different services. How do you keep them
# consistent?
#
# A distributed transaction (2PC) is not an option. I use a Saga: a sequence of
# local transactions, where each step has a compensating action in case a later
# step fails.
# - Choreography: each service listens to events and publishes its own. Pros:
# simple for 2-3 steps, no central point. Cons: the flow is "hidden" across
# many services, with a risk of cyclic events.
# - Orchestration: an orchestrator (state machine) sends commands and keeps the
# state. Pros: the flow is visible in one place, timeouts and compensations
# are easy. Cons: the orchestrator can turn into a "god service".
# Tools: MassTransit state machines, NServiceBus sagas, Azure Durable Functions,
# Temporal. The user sees intermediate states (e.g. "Pending payment"): that is
# eventual consistency, and it must be visible in the UI too.
# ======================================================================
OrderPlaced --> [Stock] ReserveStock --> StockReserved --> [Payment] Charge
|
PaymentFailed
|
compensation: [Stock] ReleaseStock <---+
[Ordering] CancelOrder <--+
|