# Version Idempotency Fingerprints Safely Across Schema Rollouts
## Trigger
Use this when a durable idempotency key can be retried while request schemas, defaults, or canonicalization algorithms are changing. The goal is to replay the original committed outcome without letting a semantically changed request reuse an old key.
## Durable invariant
Keep one uniqueness constraint on `(caller scope, operation type, idempotency key)`. Never include the fingerprint version in that constraint.
Store:
- request schema version;
- immutable fingerprint algorithm version;
- digest and, when practical, a canonical semantic-intent snapshot;
- committed outcome or stable result identifier;
- response representation version when responses evolve.
Claim the key, apply the business effect, and store the outcome in one transaction.
## Practical verification
For a new key, strictly parse the declared schema, construct the complete effect-bearing intent, fingerprint it with the current algorithm, and commit it with the effect.
For an existing key:
1. Load the record before selecting a verifier.
2. Treat its stored schema and fingerprint versions as authoritative.
3. Strictly decode the retry using its declared schema. Reject unsupported versions, unknown fields, duplicate fields, and malformed representations before fingerprint comparison.
4. Use an explicit verifier for the stored and incoming version pair.
5. Require equality for every input that can affect the effect, authorization decision, durable metadata, or committed result.
6. Replay the stored outcome only when equality is proven. Reject ambiguous, lossy, or unrepresentable conversions as conflicting key reuse.
A newer field may match a legacy record only when it has the exact documented legacy meaning, such as the legacy default. Never discard a new field merely because the old canonicalizer did not know it. Translate an old request toward a newer record using fixed historical defaults; a newer nondefault intent must conflict.
Do not redefine an old algorithm label, recompute historical records with the newest canonicalizer, compare digests from different algorithms directly, or overwrite the original digest during replay.
## Mixed-version races
Old and new attempts still contend on the same version-independent unique key. The first committed attempt fixes the key's intent and outcome. A loser reloads that record and either proves semantic equivalence and replays, or returns a conflict without performing the mutation. If the winner rolls back, another attempt may claim the key.
## Safe rollout
1. Add version columns while old writers still run. Backfill legacy rows or permanently define an unversioned value as one specific legacy version.
2. Deploy readers that understand both legacy and new records.
3. Keep writers on the legacy algorithm until every serving node can validate new records.
4. Enable new writers and clients.
5. Retain legacy parsers, canonicalizers, defaults, and pairwise verifiers through the full record-retention and retry horizon.
A server that cannot understand a request version must reject or route it before performing an effect.
## Replay and limits
Replay an immutable stored response or render a compatible response from an immutable stored outcome. Never reconstruct replay from mutable current state or rerun the mutation.
Digest-only legacy records are safe across versions only when comparison is provably complete and lossless. If an old digest omitted information needed to establish equality, use a stored intent snapshot or reject the cross-version retry. Remote effects still require receiver-side idempotency or an equivalent protocol.
## Failure prevented
This prevents one logical key from committing once per fingerprint version and prevents a changed request from matching an old key because a permissive legacy parser silently ignored a new effect-bearing field.
## Evidence
This guidance follows from transaction and compatibility reasoning, including old-first, new-first, concurrent, rollback, and lost-response cases. No implementation or runtime tests were executed.