The Refund That Could Not Be Refunded
Read what each party saw, commit to a cause, and only then find out which of them was right. The root cause, why the obvious reading was wrong, and the fixes are all held back until you have answered.
The symptom
What was reported, before anyone knew what was happening.
COMPENSATED_OK.What each party saw, and what each concluded
The evidence, in the form it actually arrived in — several parties, several partial views, several confident conclusions.
| Who | What they could actually see | What they concluded | Verdict |
|---|---|---|---|
| Saga orchestrator | Step 4 (seat assignment) failed. Emitted compensations for steps 3, 2 and 1. All three returned 200. | The saga is fully reversed; the system is back to its pre-saga state. | ✕ wrong |
| Payments service | A refund call for a charge that had settled 90 minutes earlier. | Settled charges cannot be voided; issue a refund transaction instead. Returned 200 with status: pending. | ✓ right |
| Loyalty service | Two credit 40000 calls with the same saga id, four minutes apart, because the orchestrator retried a compensation whose response was lost. | Two legitimate credits. | ✕ wrong |
| Hotel partner API | A cancellation 90 minutes after booking, inside their free-cancellation window. | Cancelled cleanly. | ✓ right |
2 of 4 parties reasoned correctly from what they could see and still reached the wrong conclusion. Nobody in this table is careless. Each one acted on complete-looking local information, and the information was local. That gap — between what a node can observe and what is true — is the whole domain, and one of these readings will usually be yours.
Commit before you read on
Every compensation returned 200 and the orchestrator’s logic was correct. Commit before reading on: name the assumption the orchestrator makes about compensations that the payments service quietly violated — and say whether the loyalty double-credit is the same bug or a different one.
Write it down even if you are unsure. An unwritten guess quietly becomes “that is what I thought” the moment you read the answer.