The network will deliver your important request twice
Retries are not an edge case, they are how distributed systems stay reliable. A client whose connection drops mid request does not know whether the server got it, so it sends again. A payment callback that is not acknowledged in time is redelivered. If "charge the card" or "credit the wallet" runs twice, you have charged a customer twice. Idempotency keys make a repeated request safe.
The idea in one sentence
An idempotent operation produces the same result whether it runs once or many times. You achieve it by attaching a unique key to the request and recording, atomically, that the key has been handled, so the second arrival is recognized and skipped.
Implementing it with the database as the referee
The database is the right place to enforce "exactly once", because a unique constraint is atomic and survives a crash. Insert the key first; if the insert fails on the constraint, you have seen this request before.
create table processed_requests (
idempotency_key text primary key,
result jsonb,
created_at timestamptz default now()
);
try {
await sql`insert into processed_requests (idempotency_key) values (${key})`;
} catch (e) {
if (isUniqueViolation(e)) return cachedResult(key); // already done
throw e;
}
const result = await doTheWork();
await sql`update processed_requests set result = ${result} where idempotency_key = ${key}`;
return result;
Where the key comes from
For client requests, the client generates the key and sends it in a header, reusing the same key on every retry of the same logical action. For provider webhooks, the provider's event id or transaction id is the key; you do not invent it, you adopt theirs. Either way, the key identifies the intent, not the attempt.
This is the same discipline everywhere
Idempotency is not a payments trick, it is a system wide habit. M-Pesa callbacks rely on it, Stripe webhooks rely on it, the queue consumer that processes a job at least once relies on it. Anywhere a message can arrive more than once, which is everywhere that matters, the handler must be safe to run again. Build it in from the start and a whole category of "we charged them twice" incidents never happens.
