Versioned Idempotency Across Canonicalization Rollouts
Preserve one mutation effect and safe replay when request contracts or fingerprint rules change while legacy receipts and mixed-version clients remain active.
Versioned Idempotency Across Canonicalization Rollouts
Trigger
Use when a retryable mutation changes request parsing, schema, defaults, derived values, or canonicalization while legacy idempotency receipts remain valid and old and new clients may retry the same key.
Practical steps
- Keep one durable unique identity across versions, scoped by authenticated caller or tenant, stable operation family, and client idempotency key. Never include request or fingerprint version in that identity.
- Give every receipt an unambiguous request-contract version and fingerprint-semantics version. Backfill legacy rows from trusted evidence or define one deterministic legacy interpretation, such as a missing version meaning the original rules. Never reinterpret an old digest with current rules.
- Define each fingerprint over every effect-relevant input: body fields, applicable path or query values, semantic headers, operation discriminator, version-pinned defaults, and captured server-derived values. The version also fixes parsing, normalization, canonical encoding, hash domain, and algorithm.
- For a new key, strictly parse the declared contract and acquire the durable unique claim before any effect. Commit the claim, business mutation, fingerprint metadata, immutable outcome, and result version in one transaction. A preliminary lookup is only advisory.
- When requests overlap, the unique constraint chooses one winner. A loser waits for conflict resolution, rereads the committed receipt, and uses the winner's stored fingerprint semantics. If the winner rolls back, another claimant may proceed; no loser performs speculative work.
- Parse a retry under its own contract, then apply an explicit directional and value-aware adapter into the stored semantic domain. Accept only if every effect-relevant distinction is preserved and the historical digest matches. Reject unknown, ambiguous, or unrepresentable values; never drop a new semantic field or accept whichever of several fingerprint versions happens to match.
- Replay from the immutable stored outcome through a version-compatible renderer. If safe rendering is impossible, return a compatibility error or the original representation; never reconstruct from mutable current state or rerun the mutation.
- Deploy all readers, legacy-version rules, adapters, and renderers across the serving fleet before enabling new-version writes. Retain them with the receipts throughout the advertised retry and rollback horizon.
Limits
A fingerprint is collision-resistant evidence rather than literal equality; retain canonical bytes when exact equality is required. If an old fingerprint discarded a meaningful distinction and trusted original intent is unavailable, cross-version equivalence cannot be proven, so reject the retry. Effects outside the database transaction require downstream idempotency or a transactional outbox with durable consumer deduplication.
Failure prevented
This prevents an ambiguous timeout from producing a second committed effect, prevents concurrent old and new clients from creating separate version-specific claim domains, and prevents a changed request from matching an old key because legacy canonicalization ignored newer meaning.
Evidence
Support is reasoned failure-sequence analysis from the cited conversation plus an independent reasoning review. No code, database, concurrency, or integration tests were executed.