Threads · 12 / 18 · Sep 7, 2026 · Apache-2.0

The key identifies the effect, not the occasion

Deriving the idempotency key from the turn, the request or the run looks reasonable and silently deletes the second legitimate action of the same turn. And there is a second decision nobody writes down — where the key is checked — that duplicates instead of losing.

Two independent decisions, and both are usually made by accident:

Get it wrong and… It looks like
What the key identifies — the occasion, or the effect work disappears the system says "already handled"
Where it is checked — before the effect, or after work duplicates the audit trail says it happened once

Axis 1 · what the key identifies

An agent decides, in one turn, to charge a subscription and an overage. Two effects, one occasion:

recordThenCharge(p, l, suscripcion, keyOfOccasion(turn));
recordThenCharge(p, l, excedente,   keyOfOccasion(turn));

expect(p.charged).toHaveLength(1);   // the overage is gone

Nothing errored. The second call returned already handled, which is exactly what idempotency is supposed to say. You are now under-billing, and the system is reporting that it works.

Keyed by the effect, both survive — and a genuine repeat is still stopped:

keyOfEffect({ customer: "ana", amount: "40.00", reason: "subscription" })
keyOfEffect({ customer: "ana", amount: "12.00", reason: "overage"      })   // a different key

Axis 2 · where it is checked

This is the one that survives design review, because everything about it reads correctly: the key is right, the unique index is real, and the retry is refused.

chargeThenRecord(p, l, suscripcion, key);
chargeThenRecord(p, l, suscripcion, key);   // the client timed out and tried again

expect(p.charged).toHaveLength(2);   // charged twice
expect(l.rows).toHaveLength(1);      // recorded once

The check runs after the money moved. So the customer is charged twice and the audit trail says it happened once — which means the duplicate cannot be found later either. It is the worst combination in the repository and the one that looks most correct while you are reading it.

The two axes are independent. A review that only asks "what is your idempotency key?" passes this code, and this code double-charges on every retry.

And a timeout is not an exotic case

for (let i = 0; i < 3; i++) recordThenCharge(p, l, suscripcion, key);
expect(p.charged).toHaveLength(1);

Any HTTP client retries when it does not get a response. Idempotency is not a feature for careful callers — it is what makes ordinary callers safe, and the traffic that exercises it arrives on day one.

Where this comes from

Both halves are from niiko, and neither was found by reasoning about it.

The first was caught while designing the agent's charge path: the key was going to come from the turn, and the question "what if it wants to do two things?" had no good answer.

The second was found months later by an adversarial audit of a public API design — the gate computed the key correctly, wrote it to an audited table with a unique index, and did both after calling the action. A retry would have published the same post twice, answered ok twice, and left one row behind.

License

Apache-2.0 — see LICENSE. This is a demonstration, not a package. Copy what you need.


Built by Vorluno — a software studio from Panamá.

// next threadThe model may supply search terms, never identifiers