Compute
Idempotency keys and safe retries
Six retry situations and the one rule behind them. An exact replay returns the prior result, while the same key with a different payload refuses. Reconcile an unknown outcome before you retry.
The one rule
An exact replay returns the prior result. The same identity carrying a different payload is equivocation, and it refuses rather than choosing between the two.
That is the whole contract. Every mutable record carries a non-decreasing version, and a late or stale attempt cannot advance state past a newer one.
Reconcile before you retry
An unknown outcome is not a failed outcome. A dropped connection tells you nothing about whether the work was admitted.
Read the job's status first. If it exists, you have your answer and there is nothing to retry. Retrying an outcome you have not read is how one intent becomes two runs.
Six situations, six different actions
| Situation | What to do | What comes back |
|---|---|---|
| Transport error, same intent | Resend the identical request with the same key | The prior result, or the work runs exactly once |
| You already hold an admission | Read the job by its identifier | The current state; never resubmit to check |
| Quote expired or no longer matches | Request a new quote and approve it | Admission returns REPLAN_REQUIRED until you do |
| You genuinely want a second run | Use a new key and a new quote | New work, and a second charge |
| Repeating a delivery | Retry the destination write | The delivery repeats; the work does not rerun |
| Replaying a schedule occurrence | Replay that occurrence | A replay of the same occurrence, not a new run |
The schedule case is worth spelling out. An occurrence key is derived from the schedule, its version and the intended occurrence, so replaying the same occurrence is always a replay.
The six idempotency scopes
Keys do not all mean the same thing, and they do not share a namespace.
- Request — one submitted call.
- Batch — one submitted batch as a whole.
- Manifest — one input manifest.
- Logical item — one item inside the work.
- Artifact — one uploaded input or output file.
- Destination write — one write to one destination.
A destination-write key is why a redelivery does not rerun the work. The work already happened; only the write repeats.
Lifetime, and what we will not publish
We publish no key lifetime, so do not code against an assumed one. Design around the scope instead.
The response tells you which case you are in. It carries the typed state, the observation time and a next action. Branch on what actually happened, never on a timer.
When a retry refuses
A refusal for equivocation means the key you reused is bound to a different payload. Do not vary the key to get past it.
Send the original payload if you meant a replay, or start new work with a new key if you meant new work. See how to read a job's counts before deciding, and how to repeat a delivery without rerunning when only the write failed.