Idempotency is a business guarantee built around stable command identity. It is not merely a unique key added after duplicates appear.
Idempotent Command Reservation
Ambiguous delivery must not become an ambiguous business effect.
return db.transaction(async (tx) => {
const owner = await tx.oneOrNone(
'INSERT INTO idempotency_keys (tenant_id, key, request_hash, status) VALUES ($1,$2,$3,\'running\') ON CONFLICT (tenant_id,key) DO NOTHING RETURNING key',
[tenantId, key, requestHash],
)
if (!owner) return replayOrConflict(tx, tenantId, key, requestHash)
const response = await applyCommand(tx, command)
await tx.query(
'UPDATE idempotency_keys SET status=\'completed\', response=$3 WHERE tenant_id=$1 AND key=$2',
[tenantId, key, response],
)
return response // reservation, domain write, and response commit together
})Invariant: One logical command produces at most one committed business effect.
Use when: Clients may retry a write after an ambiguous timeout.
Why this boundary matters
A timeout cannot distinguish a rejected command from a committed command whose response was lost. Stable command identity closes that uncertainty window.
Failure policy
| Boundary | Action |
|---|---|
| New key and valid command | Execute and store the response atomically |
| Known key and identical payload | Return the stored outcome |
| Known key with different payload | Reject as a key-reuse conflict |
| Matching command still in progress | Return pending or wait within the caller deadline |
| Key expired | Treat replay safety as unknown; reconcile before repeating |
Trade-offs
Idempotency requires durable key retention, payload fingerprints, response storage, and a clear scope such as tenant plus operation. Retaining keys forever is expensive; expiring them too early reopens duplicate risk.
Decision rule: Require idempotency whenever a caller can observe an ambiguous write outcome and reasonably retry it.
Further reference
Browse all engineering snippets · Read about reliable delivery