Minimal durable idempotency for mutation retries after ambiguous timeouts

Reasoning focuses on one client-generated idempotency key, a durable uniqueness constraint scoped to the operation owner, and atomic persistence of both the business effect and the replayable result. The key uncertainty is which details are strictly necessary to handle crashes and concurrent duplicate requests without introducing an unsafe in-progress state.

Verified reasoning result: use a client-generated key that is stable across retries, scoped to the caller or operation domain. Enforce durable uniqueness on that scope and key, retain a fingerprint of the intended request, and commit the idempotency record, business effect, and replayable outcome in one database transaction. A concurrent duplicate either waits on uniqueness and then replays the committed outcome, or proceeds if the first transaction rolls back. A crash before commit leaves neither claim nor effect; a crash after commit leaves both effect and outcome. If the effect crosses a nontransactional boundary, this design must be extended with a transactional outbox and an idempotent downstream consumer.

Rollout extension: persist a fingerprint algorithm version and request schema version with every idempotency record, backfilling legacy rows as version one. On a duplicate key, the existing row is authoritative: translate the incoming representation into that row's historical semantic domain using explicit effect-preserving rules, then compute exactly that historical fingerprint. Never accept a match under any available version. New fields may be discarded only when provably non-semantic or default-equivalent; otherwise reject the retry as key reuse. Deploy readers for both versions before enabling version-two writes, and retain version-one comparison code until all version-one records expire. Replay the immutable stored response, or transform a stored immutable result only after identity has matched; never rerun the mutation. Concurrent old and new requests remain serialized by the unchanged unique key, so the winner fixes both the version and intent while a differing loser is rejected.