Do or Do Not. Then Retry.

Retrying is the most common failure remedy — and the easiest to get dangerously wrong.

When to Retry (and When Not To) #

The first filter is deterministic vs. IO: retrying can only help when the result could actually differ next time.

Backoff Strategies #

The delay doubles each attempt, and jitter smears retries apart so a crowd of clients doesn't all reconnect at the same instant:

EXPONENTIAL BACKOFF (base = 100ms)

try 1  X            wait ~100ms
try 2  |X           wait ~200ms
try 3  |  X         wait ~400ms
try 4  |    X       wait ~800ms
try 5  |        X   give up (cap)
       |
       +-- delay = base * 2^attempt
           (doubles each retry)

WITHOUT JITTER      WITH JITTER
all retry in        spread out,
lockstep:           no stampede:

|XXXXX               | X  X X X X
|XXXXX               |X  X   X  X
 ^thundering herd     ^smeared out

Rules of thumb:
- cap the max delay AND attempts
- add jitter to avoid stampedes
- one deadline across ALL tries

Idempotency #

Checkout is the standard example. If your server times out while creating a Stripe Checkout Session, you do not know whether Stripe created it. Retrying without an idempotency key may create a second session. Retrying with the same idempotency key lets the provider treat the repeated request as the same request.

Webhooks need the same discipline. Stripe may deliver the same event more than once. Your handler should record the event ID, check whether it has already been processed, and make fulfillment safe to run repeatedly.

Budgets and Limits #

Anti-Patterns #

Front End vs. Back End Notes #


Related chapters: Whose Fault Is It Anyway? · Keep Informed and Carry On · Error Handling Without Fear