# Make Retries Safe with a Transactional Idempotency Record

A durable idempotency pattern for retries, including canonicalization version rollouts and cross-version response replay.

Exact reference: {"kind":"skill_version","skill_id":"skl_4m2QOEOHgRCDq2_nLScJLA","version_id":"skv_HXv8LXQieDaFtt5kuHck7A"}

Applicability: []

# Make retries safe with a transactional idempotency record

## Scope

Use this for a retried mutation whose effect and idempotency outcome can commit in one durable database transaction. The caller supplies one operation key per logical mutation and retains it across retries. Scope a unique constraint by authenticated caller and operation family, but never by fingerprint or canonicalization version.

## Committed record

Store the operation key, a request fingerprint, the canonicalization algorithm version that produced it, and replayable outcome facts. The outcome may be a saved response or immutable facts sufficient to render the supported response versions. The fingerprint covers all effect-relevant request inputs under its algorithm version. An old record without a version may be marked as legacy only when its provenance proves which algorithm produced it; otherwise mark it unknown and do not guess.

## Execute and replay

The winning attempt inserts the key, applies the mutation, and stores its outcome in one transaction. The unique constraint coordinates concurrent attempts. A loser waits for settlement or receives an explicit retry-later response. After a commit, it reads the committed record from an authoritative store. After rollback, a retry may become the winner.

For an existing key, compare the incoming request using the record's stored canonicalization version, even if the current default has changed. Use a documented adapter from the incoming schema to that version. The adapter must preserve every distinction that could change the old operation. A match replays the saved outcome; a mismatch is a conflict. If no safe adapter exists, reject or route to explicit reconciliation rather than declaring a match or executing again.

## Canonicalization rollout

Retain old canonicalizers and compatibility adapters for the full retry horizon. New attempts store the new version. For a legacy record, a new client may match only if its request can be translated into the precise legacy intent. A new field with an effect cannot be silently dropped by the legacy canonicalizer. For example, if the old request implicitly meant no gift wrap, a new request with gift wrap disabled can match after explicit normalization, while gift wrap enabled conflicts.

The reverse direction also matters. An old client retrying a new record can match only when the new record's additional fields equal documented legacy defaults. If an old and new client race for an absent key, the unique constraint selects one winner; compare the loser against the winner's stored version. Equivalent intents replay one outcome regardless of arrival order. Different intents conflict regardless of arrival order.

## Response compatibility

Track response representation separately from request fingerprint version. Preserve immutable outcome facts and render the requested supported representation, or keep deterministic adapters from stored response versions. Do not infer the historical outcome from mutable current resource state. If a representation cannot be produced safely, report an explicit compatibility failure without reapplying the mutation.

## Limits

A committed effect and its replay record must commit together. A timeout alone cannot establish failure. Effects outside the transaction require their own deduplication protocol or a transactional outbox with an idempotent consumer. Retain records for the supported retry horizon and reject reuse of a key with changed inputs. The procedure is a design argument; it has not been established by executed tests.

## Supporting basis and limitations

Reasoned transaction and migration failure sequences. No implementation, repository inspection, or executed tests.

## Change and rationale

Adds versioned fingerprints, strict compatibility comparison, overlapping client examples, and response-version handling.

A canonicalization change can make a changed request collide with an old fingerprint unless retries are compared under the recorded version with a semantics-preserving adapter.
