# Durable idempotency for retryable mutations
## Trigger
Use this pattern when a caller may retry after an ambiguous response, especially while request parsing, defaults, field meanings, or canonicalization rules are changing.
## Practical steps
1. Give each logical mutation one high-entropy idempotency key. Reuse it for every retry and scope uniqueness to the authenticated actor or tenant plus operation and key. Do not include fingerprint version in the uniqueness key.
2. In one durable transaction, claim the unique key, apply the business mutation, store an immutable outcome, and commit. A competing request waits for that transaction to commit or roll back; it never performs a check-then-act sequence outside the uniqueness boundary.
3. Store an immutable `fingerprint_version`, request fingerprint, and outcome version in the receipt. Treat legacy rows without a version as one named legacy version, never as whatever version is current.
4. For a new key, the winner chooses the enabled fingerprint version. For an existing key, the receipt version is authoritative. Parse the retry under its declared wire schema, convert it to semantic intent, and project it losslessly into the stored version. Reject reuse if any effect-defining field, default, precision, or meaning would be discarded, invented, or conflated. Never accept a retry merely because any available version produces a matching digest.
5. If a legacy request wins, an upgraded retry waits and then proves its downgrade to the legacy intent is lossless. If an upgraded request wins, a legacy retry is promoted using explicit historical defaults and matches only when it expresses the same intent. The winner fixes both the effect and its comparison semantics.
6. Deploy readers for old and new receipt versions before enabling new-version writes. Gate writers until every serving node can evaluate the new version. A node that cannot evaluate a stored version must fail closed or route to a capable node without running the mutation.
7. Replay the immutable stored response, or render a negotiated response from an immutable semantic outcome. Do not recreate the mutation from current state.
8. Retain every canonicalizer and compatibility adapter until all receipts using it expire. A digest alone cannot be migrated safely to a different canonicalization version.
## Limits
A cryptographic digest has negligible rather than impossible collision risk; store and compare canonical intent bytes when exact equality is required. Retention defines the deduplication horizon. Effects outside the local transaction require a transactional outbox and downstream idempotency or another coordinated guarantee.
A worker crash or deadline proves an external action stayed absent only when failure occurred before dispatch or authoritative recovery confirms cancellation. A timeout after dispatch is ambiguous: recover it using the same operation identifier and never retry it under a new identifier.
This design is reasoned analysis, not executed validation. Verify transaction isolation, uniqueness conflicts, every supported version pair, lossy-adapter rejection, mixed-version races, crash windows, and downstream recovery in the actual system.
## Failure prevented
This prevents a schema rollout from making a materially changed request match an older key, and prevents overlapping legacy and upgraded retries from committing the same logical mutation twice.