Sometimes the most resilient thing a system can do isn’t retry.
Most resiliency discussions focus on retries, timeouts, and circuit breakers.
But some of the most important resiliency patterns happen after the failure.
That’s where compensating transactions come in.
Resiliency Is About Recovery
A common mistake is thinking resiliency means preventing failures.
Failures are inevitable.
Networks fail. Services crash. Messages get lost. Requests time out.
True resiliency is accepting that failures will occur and having a plan to recover when they do.
Sometimes recovery means correcting actions that may already have occurred.
A Real-World Example
Have you ever swiped your card at a store, received a charge notification, only to have the terminal report an error and later discover that the charge was nowhere to be found?
What happened?
The point-of-sale terminal sent an authorization request.
But before it received a response, something failed: a network issue, a timeout, or a problem somewhere in the payment flow.
Now the terminal doesn’t know whether the transaction succeeded or failed.
The authorization request may have reached the card issuer and been processed, or it may not have.
Rather than risk leaving the customer incorrectly charged, the terminal sends a second transaction: a reversal.
The Compensating Transaction
That reversal is a real-world example of a compensating transaction.
Its purpose is simple:
Undo the effects of a previous action if that action completed successfully. If the original authorization never happened, nothing changes.
If it did happen, the reversal corrects it. Instead of determining exactly what happened, the system performs a corrective action.
Beyond Payments
Compensating transactions show up in many real-world distributed systems:
- Releasing inventory after a failed order
- Refunding a payment after a fulfillment failure
- Canceling a reservation when verification times out
The pattern is always the same: something failed, and the system takes a corrective action.
Final Thoughts
When engineers think about resiliency, they often focus on preventing failures. But distributed systems fail in unexpected ways.
Sometimes the most resilient thing a system can do isn’t retry. It’s correct the mistake and move forward.