Call a method in the same process and it returns a value or it throws. Two outcomes, and both are information: either way you know what happened, so you can write the next line of code accordingly.
Put a network between the caller and the method and most engineers' mental model quietly stays the same: it worked, or it failed. That model is wrong, and the gap between those two outcomes is where the money goes missing.
Three outcomes, two of them identical
A client calls a payment service. Three things can happen:
| What happened | Did the money move? | What the client sees |
|---|---|---|
| The request arrives and the reply comes back | Yes, charged | 200 OK |
| The request never arrives | No | timeout |
| The request arrives and no reply comes back | Yes, charged | timeout |
Look only at the right-hand column, because that is all your code can see. Two different states of the world, the customer's money untouched and the customer's money gone, arrive at your service as byte-identical timeouts. Nothing available to the caller separates them.
Every repair works blind
Because your code cannot tell those two cases apart, every repair has to work without knowing which one happened. The course builds the rest of its material on that column.
You have probably met this already. You wrote if (orderExists) return existing; before an insert. You added a UNIQUE constraint on a reference number and caught the violation. You built a nightly reconciliation job that fixes up rows nobody meant to create twice. Each of those was a way of handling the third outcome without a name for it.
What about an HTTP 500?
Common Mistake
Reading a 5xx as proof that nothing was committed. An exception thrown after the commit returns 500, a gateway that gives up waiting returns 504, and one whose backend connection broke mid-reply returns 502, in every case with the money possibly moved.
Unless the service guarantees that a 5xx means nothing was committed, treat it like a timeout and retry with the same key, so that a second attempt cannot charge twice.


