A capability stays maintainable only when the team can explain every state, retry, and piece of residual data—not merely show one successful run. Committed saga steps cannot be rolled back by ACID; compensation is a new business action. Persist step state and compensation idempotency keys.
Distributed correctness comes from idempotency keys, leases, monotonic versions, and reconcilable facts—not an assumption of one delivery. A timeout means unknown outcome, not confirmed failure.
Questions the design must answer
This capability crosses clients, networks, and servers, so a local optimization can create a system failure. Decisions must constrain both endpoints, persisted truth, and operating budgets together.
- Classify steps as reversible, compensatable, or irreversible; on cancel stop scheduling, settle in-flight results, compensate in reverse, and record residue.
- Give state one owner, a version, and terminal states; callbacks may mutate only the version that created them.
- Use explicit capability negotiation so older clients receive an explained fallback instead of a half-working state.
The delivery standard for Cancellation in Long-Running Sagas Is Not a Database Rollback is a usable normal path, convergent failures, bounded resources, and a state users can understand. The result is a production capability that can be explained, degraded safely, and rolled back—not a demo that works once.
Edge cases are part of the feature
Production failures often appear when two individually valid actions overlap. Inspect stale messages, duplicate effects, exhausted resources, and mixed versions instead of patching only the current stack frame.
- Concurrent cancel and completion can show opposing terminal states, while hidden compensation failure leaves quota, temporary objects, or notifications behind.
- Fixing only the UI leaves queues, locks, or expired credentials for the next operation to inherit and fail again.
- An untested fallback receives all traffic during a primary failure and becomes the slower, more expensive bottleneck.
Prove that it works with evidence
A release gate combines deterministic regression, randomized timing, and real browser pairs. Preserve the seed and state trace from every failure as a permanent replay case.
- Inject cancel and crashes before and after every step commit, repeat compensation, and verify terminal matrices, residue lists, and user messages.
- Drive the state machine with reordered, duplicate, and delayed messages, proving stale versions are ignored and explicit stop survives recovery.
- Before release, record success rate, p50/p95/p99 latency, error classes, and resource high-water marks with explicit rollback thresholds.
The release standard is practical: the normal path is fast, abnormal paths converge, recovery never overrides an explicit user decision, and operators can diagnose faults from limited, privacy-safe evidence.