Prevent Duplicate API Operations After a Timeout

A client timeout does not prove that a POST failed. The server may have committed the operation while its response was lost. Make creation requests retryable by assigning the logical operation a client-generated idempotency key and reusing that same key for every retry.

Last updated: October 4, 2026.

CREATE TABLE ApiOperation (
  TenantId       bigint        NOT NULL,
  IdempotencyKey varchar(64)   NOT NULL,
  RequestHash    char(64)      NOT NULL,
  OperationId    uniqueidentifier NOT NULL,
  Status         varchar(20)   NOT NULL,
  ResponseJson   nvarchar(max) NULL,
  CreatedAt      datetime2     NOT NULL DEFAULT SYSUTCDATETIME(),
  CONSTRAINT PK_ApiOperation
    PRIMARY KEY (TenantId, IdempotencyKey)
);

Insert the idempotency record and start the business operation in the same transaction. If the key already exists, compare the request hash. Return the saved operation identifier or response for an identical request, and reject the key if it is reused with a different payload.

Treat the key as the identity of one intent

Generate the key before the first attempt and persist it on the client until the outcome is known. Scope it to the authenticated tenant or account. Do not generate a fresh key during an automatic retry, because the server would correctly treat that as a new operation.

RFC 9110 explains that clients should not automatically retry a non-idempotent method unless they know its semantics are idempotent or can determine that the first request was not applied. See its idempotent methods section. The key plus the atomic record supplies that application-level guarantee for a POST.

Return status instead of holding the connection open

For a long operation, return 202 Accepted with an operation ID and a status URL. A repeated POST with the same key should return the same operation identity. The client can then poll the status resource or receive a webhook without guessing whether another operation should be created.

AWS’s idempotent API guidance likewise recommends a unique caller-provided request identifier and an atomic server-side record. For related designs, see idempotent webhook processing, tenant-safe background jobs, and HTTP API integration in PHP.

Related Web Cheat Sheet guides

Sergey Kornilov

Sergey Kornilov