Effect commit and compensation: recover without pretending the world rewinds
Separate local commit boundaries, external receipts, transactional outboxes, and conditional saga compensations.
On this page
The question for today
What you’ll understand
- Identify which facts can share an actual transaction.
- Design effect-aware compensation with receipts and preconditions.
- Distinguish successful remediation from restoration of an identical prior world.
An agent often coordinates changes across systems that do not share a transaction. Recording a successful step, committing a remote effect, and publishing an event can fail independently. Recovery needs a protocol for those boundaries. A compensation can restore a useful business condition, but it does not generally erase time, observations, fees, or other actors' intervening work.
Name the actual atomic boundary
If an effect and its journal record live in one transactional database, an application can design them to commit together under that database's isolation and durability semantics. A remote API call cannot be included merely by placing it between begin and commit in local code. A transactional outbox can commit local intent and an event record together, then relay the event later. Debezium's outbox router is a concrete implementation component for such records; its configuration is not a global transaction across every consuming service.
An outbox relay can redeliver after uncertainty, so downstream consumers still need appropriate deduplication and effect handling. A provider may instead expose a prepare/commit or conditional-write protocol, but that must be an actual supported contract. Otherwise persist the effect identity and reconcile receipts around the external gap. Distinguish intended, dispatched, provider-committed, and locally-recorded states. A local commit failure after a remote success is an unresolved coordination problem, not proof that both systems rolled back.
A compensation is another effect with its own contract
A saga breaks a longer operation into steps with compensating actions for the chosen failure policy. Register recovery intent before or alongside the corresponding effect boundary so a crash does not lose the knowledge that remediation may be needed. A compensation should inspect the original receipt and current state, and be safe under retry according to its own idempotency identity. Reverse order is useful for some dependency chains, but compensation ordering follows the actual dependencies and business rules rather than a universal stack rule.
Conditional compensation protects intervening work. If a resource has changed since this run's effect, blindly restoring an old snapshot can overwrite another actor's update. Use expected version, ownership, or another supported precondition, then report a blocked remediation when it fails. A resource may be nonrefundable, externally observed, or irreversibly delivered. In those cases compensation is a new corrective action or explicit unresolved obligation, not a mathematical inverse. Test its authorization and budget independently from the forward action.
Evaluate recovery outcomes beyond a binary rollback label
Track confirmed forward effects, attempted compensations, successful remediations, blocked preconditions, and unresolved outcomes. Include crashes before and after each remote commit and after each compensation receipt. If compensation itself times out, preserve its identity and reconcile it rather than compensating the compensation blindly. Distinguish a workflow that has stopped from one whose external obligations are settled. Report the remaining resources and required follow-up concretely so a terminal label does not hide a live reservation or pending write.
The function lab illustrates information loss in a simple mapping. Reset, set a=1 and x=1, predict y=1, then Play or Step. Separately Reset, set a=1 and x=−1, predict the same y=1, then Play or Step. The square alone cannot identify which original sign produced it. This is not a saga or external-effect simulator, but it shows why a reverse action needs retained context and a declared goal. The real compensation still needs receipts, ownership, and current-state checks rather than an assumed inverse.
Work it through
A version check can block unsafe remediation
A run changes resource A from version ten to eleven and B from twenty to twenty-one. Before recovery, another actor changes A to version twelve. Proposed compensations require the exact post-effect versions, and successful writes advance versions.
B still matches expected version twenty-one, so its authorized compensation can restore the intended business value and advance B to version twenty-two.
A is at twelve rather than eleven, so its conditional compensation is rejected instead of overwriting the intervening update.
Of two planned compensations, one succeeds and one is blocked. Even B's successful remediation does not return its version history to twenty; the journal must retain both effects and the unresolved A obligation.
The recovery performs one safe corrective write and preserves one blocked obligation, rather than claiming the whole world rolled back.
The living notebook
Explore the model
Interactive lab · function
A forward result may not identify its origin
Reset, set a=1 and x=1, predict y=1, then Play or Step. Separately Reset, set a=1 and x=−1, predict y=1, then Play or Step. The fixed quadratic has no effects, receipts, versions, or compensation protocol.
- y at chosen x
- 0.608
- Tangent slope · 2ax
- 1.35
- Signed area · ax³/3
- 0.182
This lab uses only y = ax². Playback traces the curve within the fixed integration interval from 0 to x; it does not estimate numerical error or change the chosen point. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forRecovery needs retained identity and current-state conditions, not an assumed inverse.
Pause & reason
Check your understanding
Your turn
Try it yourself
A fictional quota starts at 100 units. An operation consumes thirty and an irreversible processing fee consumes five. A compensation returns the thirty-unit reservation only. What remains, and did the compensation invert the entire sequence?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Account for the fee separately from the returned reservation.
Compare with the solution
The sequence is 100−30−5+30=95 units. The reservation was restored, but the five-unit fee remains, so the global sequence was not inverted. The example requires the fee and refund rules to be part of the declared effect contract.
Keep the idea
Take it with you
- Local atomicity does not extend to remote services automatically.
- Compensations are conditional retryable effects with separate obligations.
- Business remediation and identical historical rollback are different outcomes.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.