Saga pattern in .NET microservices: keeping order, stock and payment consistent (flow diagram)

A distributed transaction (2PC) is not an option.

text
 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 <--+