Replay idempotent mutations across request canonicalization rollouts
Preserve one committed effect across schema rollouts with stored fingerprint rules, safe semantic mapping, fresh-snapshot conflict recovery, and compatible replay.
Versioned idempotency for retried mutations
Trigger
Use when a mutation's request contract or canonicalization changes while older idempotency receipts or clients may still retry, including mixed-version requests racing on one key.
Practical steps
- Keep one database-enforced unique key scoped to the authenticated caller or tenant and stable operation family. The key's uniqueness does not include schema or fingerprint version. Cover every effect-relevant input in the scope or fingerprint, including target, path, semantic headers, version-pinned defaults, and captured server-derived values.
- In one transaction, claim the key, apply the local business effect, and commit a receipt with the trusted request-contract version, fingerprint-scheme version, digest, immutable outcome, and response version. A fingerprint scheme fixes parsing, semantic projection, canonical encoding, and hashing. Identify the incoming contract through a trusted protocol boundary.
- On a duplicate key, the committed receipt defines the comparison rules. Parse the retry under its own contract, then use an explicit value-aware mapping into the receipt's historical semantic domain. Compare under the stored fingerprint scheme only when every effect-relevant distinction survives. Reject changed, unknown, or unrepresentable intent; never accept a match under whichever scheme happens to fit.
- Let the unique constraint resolve concurrent old and new attempts. After a conflict or serialization failure, read the committed receipt in a fresh database snapshot before comparing. Restart a transaction with a fixed snapshot when necessary; an invisible row in an old snapshot is not proof that the claimant rolled back. Only a confirmed rollback permits another attempt to claim and execute.
- Replay from immutable outcome facts, rendering a compatible response when possible. Tag legacy receipts with their known generating versions; reject cross-version comparison when historical intent cannot be established. Deploy new readers before new writers, and keep readers, mappings, and rollback targets compatible with every retained receipt for the retry lifetime.
Limits
The guarantee is at most one committed local effect per retained key. Expiring a receipt permits later reuse. Effects outside the transaction need downstream idempotency or an outbox with consumer deduplication. A historical digest that erased meaningful distinctions cannot prove equivalence without trusted original intent.
Failure prevented
This blocks duplicate local effects after a lost response, changed requests matching an older weaker canonicalizer, and a racing retry acting because its fixed snapshot cannot yet see a committed receipt. It also prevents a rollback binary from mishandling still-valid newer receipts.
Evidence
This is transaction and isolation-level reasoning, including an independent reasoning audit. No implementation was inspected and no tests were executed.