TT Lab
Get started
Learn Learning paths Courses

Idempotency — Two Clicks, One Charge

Design principles: Idempotent requests still need retry budgets

Continue in TT Lab

In one line

A retry is not "one more time"; it is a policy of resending a safe request within the remaining time and the remaining number of attempts.

Why this was needed

When clients retry all at once against a slow service, more requests pile up in a queue that is already backed up. If you set a 5-second timeout on each request and make 3 attempts, the whole job does not finish within 5 seconds. You have to compute the deadline at the start, and recompute the remaining time before each call and each wait. Even with an idempotency key, cost, load, and user waiting time do not go away.

How it works

send(남은 시간) → 응답 → 재시도할 상태인가? → 재생해도 안전한가?
                                                ↓
종료 ← 횟수 또는 전체 예산 소진 ← 지터 + Retry-After 대기 계산
                                                ↓
                                            sleep → 다음 호출

This lab's policy retries only 429, 502, 503, and 504. GET, HEAD, PUT, and DELETE are allowed on the premise of this API's idempotency contract, and POST is allowed only when it has a key that is not blank. If the server does not actually process that key atomically, just attaching a string on the client is not safe. The earlier idempotency lab deals with exactly that server-side premise.

What it looks like in the field

Adding jitter to exponential backoff reduces the phenomenon where all clients wake at the same moment. If the server's Retry-After is longer than the local wait, follow the longer value. A server wait longer than the whole budget is not shortened arbitrarily to retry early; the current response is returned. Here we state the limitation that only the integer-seconds format is supported and the HTTP date format is not.

What you will do in the next lab

You will verify the 8 steps without real waiting, using a fake monotonic clock, sleep, and send. The premise is that send is an adapter that responds within the remaining time it receives. If a synchronous function blocks forever, the executor cannot forcibly stop it, so a real HTTP adapter needs a separate timeout setting. The budget and the maximum count include the first attempt. Do not retry every status, and do not treat a 412 conflict as a network failure.

Reference: HTTP idempotent methods