Most teams test the forward write until it passes, then document the undo in a runbook and trust an operator to run it by hand under pressure. That is backwards. The compensating action is a second, separate business transaction with its own rules, and it fails in its own ways: it can double-apply, it can fail after partial success, and it can assume state that no longer exists. Microsoft's pattern guidance is explicit that you often cannot simply restore the original state, because concurrent work may have changed the data, so the undo has to apply business rules of its own the Compensating Transaction pattern.
Sagas make the same point from the orchestration side: there is no automatic rollback across services, and a developer must design the compensating transactions that explicitly undo earlier steps the Saga pattern. Temporal frames compensations as a first-class part of the long-running transaction: either the forward steps complete or the executed operations are undone as if they never happened, and how to compensate each operation depends on the scenario compensating actions.
If the compensation is real code that runs in production, it should be tested like real code. The dry-run endpoint is how you do that without pointing it at a live order or a live payment.
A finance architecture walkthrough draws the line that matters here: compensation is a new business action, not an erase. A void, refund, credit note or reversing entry has its own rules and evidence, and it can itself fail, so it needs an operation ID, idempotency behavior, workflow state and an escalation path idempotency, compensation and reconciliation. Testing the inverse call is testing that new action.



