A client can lose an HTTP response after the server has committed the requested mutation. From the client’s perspective, the operation is unresolved: the connection failed, but that failure does not reveal whether durable state changed. Retrying the same POST can then create a second order, payment attempt, reservation, or other mutation.

An idempotency key gives the retry a stable identity that is separate from any single transport attempt. The server can associate repeated requests carrying that identity with one logical operation. That mechanism narrows an ambiguity at the API boundary, but the key alone is not a guarantee. Its scope, persistence, request comparison, concurrency control, and replay policy determine what repeated delivery actually means.

Transport attempts and logical operations are different identities

A TCP connection, HTTP request instance, trace span, and application mutation can all have different lifetimes. A retry creates a new transport attempt even when the caller intends the same application operation.

The idempotency key represents that application-level identity. A client generates a key before the first attempt and reuses it only for retries of that same intended mutation. A new mutation receives a new key.

This separation matters because transport metadata is not stable enough to identify intent. Source ports can change. Connections can be replaced. Proxies can retry requests. Trace identifiers may describe observation rather than business identity. None of those values automatically defines whether two deliveries are one mutation or two.

The server therefore needs an explicit mapping such as:

(scope, idempotency_key) -> operation record

The scope is part of the contract. It might include an authenticated account, API tenant, endpoint, or another namespace. Without a defined scope, the same key value from unrelated callers can collide.

The first accepted request establishes request identity

A repeated key is useful only if the server can detect accidental reuse with different request semantics. Suppose a client sends key K with one amount, then later sends the same key with a different amount. Returning the result from the first mutation without checking the request can hide a caller defect.

A common design stores a canonical request fingerprint beside the key. The fingerprint can cover the fields that define the mutation while excluding transport-only values. On a repeated key, the server compares the new request with the stored identity.

The comparison rule must be explicit. Hashing raw JSON bytes, for example, treats insignificant serialization differences as distinct unless the API requires byte-for-byte identity. A semantic fingerprint can normalize selected fields, but that normalization becomes part of the API’s equivalence rule.

The stored record can conceptually contain:

key
scope
request_fingerprint
state
result_reference
created_at
expires_at

A mismatch between the repeated request and the stored fingerprint should not silently become a second mutation under the same key. The API needs a defined conflict response for that case.

Concurrent duplicates require atomic ownership

Two requests carrying the same new key can arrive at nearly the same time. A check followed by an insert is insufficient if both requests can observe the key as absent before either records ownership.

The transition from “key absent” to “operation claimed” needs an atomic boundary. A database uniqueness constraint on (scope, key) is one common primitive. One request creates the operation record; a competing request encounters the existing record and follows the duplicate path.

That atomic claim does not by itself make the business mutation atomic. The operation record and the durable state change still need a consistency strategy. If both live in the same transactional database, they can often participate in one transaction or in a state machine whose transitions are protected by transactions. If the mutation crosses external systems, the API cannot manufacture a single local transaction around resources that do not share one.

The key mechanism should therefore be described as duplicate coordination, not as universal exactly-once execution. External effects may require their own idempotency identity, deduplication contract, or reconciliation process.

An in-progress record has observable semantics

A duplicate can arrive while the first request is still executing. At that point there may be no completed response to replay.

The operation record needs a state that distinguishes an active claim from a completed result. A repeated request can then receive a defined response, wait for completion under a bounded policy, or poll another resource. The choice depends on the API contract.

Simply running the mutation again defeats the coordination boundary. Treating every in-progress record as permanently successful is also incorrect because the first attempt may still fail.

Crash recovery adds another state transition. A process can claim the key and terminate before recording completion. If the claim has no recovery rule, the key can remain stuck. If another worker may take over, the takeover rule must distinguish safe resumption from repeating an external side effect whose outcome is unresolved.

This is the same uncertainty that motivated the key in the first place, now inside the server boundary. Durable operation state reduces ambiguity only to the extent that each side effect participates in a recoverable protocol.

Response replay is part of the contract

After completion, a duplicate request often needs the outcome of the original logical operation rather than a fresh execution. That can mean storing the original response, storing a reference to the created resource, or reconstructing a response from durable state.

These choices are not equivalent. Replaying stored status and body preserves the original API result. Reconstructing later can expose state that changed after the original operation. Returning only a resource reference can be sufficient when the API contract defines that representation, but it is not identical to replaying the first response.

Headers also need a policy. Some headers describe the original representation, while others are generated per transport attempt. A server should not assume that every header from the first response belongs in later responses.

Failure results require similar precision. If validation fails before the key claims a mutation, the server may permit a corrected request with the same key. If execution starts and produces a durable terminal failure, repeated delivery may need to replay that failure. The boundary between those cases must be tied to the operation state machine rather than to a generic rule that all errors are cached.

Retention defines the deduplication window

Idempotency records consume storage, so systems commonly retain them for a finite period. Expiration changes semantics: after the record disappears, the same key can look new again.

The API therefore has a deduplication window, whether it is stated directly or emerges from storage policy. Client retry behavior must fit inside that window if the client expects duplicate suppression.

Expiration also interacts with delayed requests. A retry can remain in a queue, proxy, or client scheduler longer than expected. If it arrives after the record expires, the server may accept it as a new operation. Retention is consequently part of correctness, not just housekeeping.

Deleting records based only on creation time can also be unsafe for long-running operations. A record should not expire while it still protects an active mutation unless the state machine has a separate recovery rule that preserves duplicate coordination.

Idempotency does not make arbitrary retries safe

A stable key addresses repeated delivery of one intended mutation. It does not decide whether the caller should retry, how long retries should continue, or whether an operation remains useful after its deadline.

Retry policy still needs bounds. A caller can stop after its deadline even though the server may finish the operation. Backoff can reduce repeated pressure during partial failure. A retry budget can cap amplification across service layers.

The key also cannot merge two independently intended operations. If a caller accidentally reuses a key for a later purchase, the correct behavior is conflict detection, not deduplication into the earlier purchase.

This distinction keeps the mechanism narrow: the key binds attempts that the caller declares to be the same logical mutation. It does not infer intent from similar payloads.

The durable record is the real synchronization boundary

The visible API feature is a request header or field, but the substantive mechanism is the durable operation record behind it. That record establishes ownership, request identity, execution state, result semantics, and retention.

When those pieces are explicit, retries can cross connection failures without automatically multiplying mutations. When they are omitted, an idempotency key can become little more than a label attached to repeated requests.

The useful design boundary is therefore not “accept a key.” It is “define one logical operation whose identity and state survive repeated transport attempts.” That contract makes duplicate handling inspectable at the same layer that owns the mutation.