Start with the state the business can accept
A saga compensation is a new business action that addresses an earlier committed action. It is not a promise to restore every participating system to its original state. The architecture needs to name the state it can reach after failure, including any external effects that remain visible.
Consider a proposed booking workflow: reserve capacity, capture a payment and issue a confirmation. If confirmation fails after the first two steps commit, deleting the local booking row does not release external capacity or reverse the payment. Conversely, refunding a payment cannot make the original charge disappear from an external provider's history.
This article supplies a proposed recovery matrix and workflow decision record. They are design artifacts for a fictional workflow. No payment, reservation or compensation provider was invoked. Their purpose is to make recovery obligations reviewable before the happy-path implementation hides them.
Draw the commit boundaries before drawing the arrows
Each participant commits locally. The coordinator may know that a request was sent without knowing whether the participant committed it. A timeout therefore creates uncertainty, not automatic evidence that nothing happened. The next action may be to query the participant by a stable operation identifier rather than submit an opposite action immediately.
The proposed workflow records a reservation identifier, payment operation identifier and confirmation outcome under one saga identifier. Each step also has a durable status that distinguishes requested, confirmed, uncertain and failed. These labels are a proposed vocabulary, not a universal saga protocol. Their usefulness depends on participants exposing enough evidence to resolve uncertain outcomes.
Microsoft's saga pattern guidance describes sequences of local transactions with compensating or continuing actions after failure. The separate compensating-transaction guidance explains that compensation is business-specific and may not restore the original state, especially when concurrent work has changed it.
A durable outbox can help publish a local state change and its outgoing message consistently. It does not supply the business meaning of undoing a payment or releasing a reservation. The outbox crash-case article tests that local publication boundary; this design begins where independent participants have already made their own commitments.
Define compensation against the owned resource
Suppose the workflow reserved one capacity allocation. Its compensation should release that identified allocation if release remains valid. It should not write an old total-capacity value back over the current value. Other bookings may have arrived since the original reservation, and a snapshot overwrite would erase their legitimate changes.
The same principle applies to payment recovery. Refer to the original provider operation and use its supported refund or cancellation contract. Distinguish a requested refund from a confirmed one. The design must account for rejection, delayed confirmation and an uncertain network response without claiming a fictional payment rule applies to every provider.
| Committed or uncertain step | Proposed recovery action | Evidence needed for completion |
|---|---|---|
| Reservation confirmed | Release its specific allocation | Participant confirms that allocation is released |
| Payment captured | Request supported compensation for that operation | Provider confirms the resulting payment state |
| Payment response uncertain | Resolve the original operation first | Stable operation lookup establishes its outcome |
| Confirmation already delivered | Correct the customer-visible status | Product-defined communication and support outcome |
| Compensation repeatedly unresolved | Enter an owned manual-review state | Named owner accepts the case with its evidence |
The table deliberately avoids a generic "rolled back" terminal label. Released capacity, a confirmed refund and a corrected customer message are different observations. A system can complete one while another remains unresolved. Record the partial state rather than hiding it behind one success flag.
Compensation order should follow dependencies and business risk. It need not be the exact reverse of the forward call order. For example, releasing capacity before resolving whether a booking can still be fulfilled may violate a product decision. The matrix asks the team to decide that relationship instead of treating a reversed arrow as a specification.
Make recovery resumable when the recovery itself fails
A compensation call can time out after it commits, just like a forward call. Give each recovery operation a stable identity and define repeat behavior at the participant boundary. Retrying a refund with a new operation identity is not equivalent to retrying the same intended refund.
The coordinator's journal should persist the intended action before dispatch where the chosen storage and messaging design supports that sequence, then record evidence of the result. After a restart, it needs to distinguish an action that was never sent from one whose outcome is unknown. A local retry counter alone cannot resolve that distinction.
The proposed failure drill sheet contains five cases: uncertain forward payment, lost compensation response, coordinator restart, concurrent resource change and an irreversible customer-visible effect. Every outcome cell is pending. Running those cases against the actual participants is the work required to turn the design into evidence.
Use bounded retries and an escalation policy when an outcome cannot be resolved automatically. A manual-review state needs ownership, the relevant operation identifiers and a clear list of actions already attempted. It is not a garbage bin labeled "retry later." Avoid including unnecessary customer payloads in a diagnostic packet; the audit-log design article separates useful event evidence from excessive data retention.
Reserve the word complete for a defined outcome
A workflow can finish successfully, recover to an accepted alternative or remain unresolved. Those states have different product meanings. If the booking cannot be fulfilled but its capacity is released and payment compensation is confirmed, the product may call the outcome canceled. If the payment state is still uncertain, that same label could mislead the customer.
The decision record therefore asks for an invariant and evidence at each terminal state. "Canceled" might require no active allocation and a confirmed supported payment outcome. "Manual review" might require a named owner and visible unresolved obligations. These are example criteria to adapt, not claims that every booking business uses the same contract.
There is also a point after which forward recovery is preferable to compensation. If a physical service has already been delivered, reversing an earlier database flag may be meaningless. The workflow needs an explicit decision about what remains compensable and who handles the remaining obligation. Place that decision near the irreversible action in the design.
Review the recovery matrix alongside the normal workflow before implementation. If a participant cannot identify an earlier operation or expose its outcome, record the resulting uncertainty as an architectural constraint. The useful guarantee is the business state the system can demonstrate, including what it cannot automatically repair.
Sources
Documentation checked .

Dreamtsoft Editorial
Releasing the identified allocation makes the concurrent-booking case concrete. Restoring an old capacity total would overwrite work that belongs to another booking.
Dreamtsoft Editorial
An uncertain payment response needs an operation lookup before choosing a recovery action. The timeout alone cannot establish whether the forward operation committed.
Dreamtsoft Editorial
The customer-facing cancellation label needs the same evidence as the internal terminal state. An unresolved payment should remain visible to whoever owns the case.
Dreamtsoft Editorial
A lost compensation response is worth testing independently from a failed forward call. The recovery operation needs repeat behavior that preserves its original identity.
Dreamtsoft Editorial
Manual review becomes actionable when it records an owner and the unresolved obligation. A generic retry status gives the next operator little basis for deciding what is safe.
Dreamtsoft Editorial
The already-delivered confirmation exposes a limit of compensation. A later database change cannot retract what the customer has read, so communication has its own completion criterion.
Dreamtsoft Editorial
The proposed matrix leaves provider outcomes pending. Filling those cells requires evidence from the actual participants before the workflow can promise an accepted recovery state.