Idempotent business commands

Bind the retry key to the original request

Store the key, account scope and material payload together before executing. Matching retries can reuse the outcome, while conflicting reuse receives an explicit error.

In this article

Define the scope and fingerprint

Choose the namespace in which a key is unique, such as account plus operation type. Authenticate the caller before looking up a result and verify access again when returning it.

Normalise the material request fields and calculate a stable fingerprint or store the canonical values. Include target, amount, currency and other fields that change the operation's meaning. Exclude transport-only details where appropriate.

Document default handling. If an omitted field and an explicit default are considered equivalent, apply the same normalisation before both initial storage and retry comparison.

Claim the key under a uniqueness rule

Use an atomic insert or equivalent storage operation to create the request record. A separate read followed by an insert can race when two requests arrive together.

SQL example
CREATE TABLE command_requests (
  account_id text NOT NULL,
  operation text NOT NULL,
  request_key text NOT NULL,
  request_fingerprint text NOT NULL,
  state text NOT NULL,
  result jsonb,
  PRIMARY KEY (account_id, operation, request_key)
);

This schema is illustrative and omits lifecycle timestamps, retention and operational indexes. The application still needs a state machine, fingerprint comparison and a transaction strategy for the actual effect.

Resolve an existing record deliberately

If the key already exists, compare the fingerprint. A mismatch is conflicting reuse and should not execute. A completed matching request can return its recorded result, subject to access and the documented response contract.

For an in-progress request, return a pending status, wait within a bounded interval or use another explicit policy. Do not let every concurrent caller start the effect independently.

Define which errors are retained. Provider behaviours differ, and the application's contract should distinguish validation failures before execution from outcomes after an operation began.

Commit or reconcile the effect

For a local database mutation, bind the business change and result record in one transaction where possible. For an external call, forward a stable downstream key and preserve uncertainty when the response is lost.

Make the client retain its key across retries and page-level recovery for the same intention. A button that generates a fresh key on every retry defeats the server's work.

Test simultaneous calls, changed payloads, process interruption and result retrieval after permissions change. The implementation should explain whether a request is new, matching, conflicting or unresolved before deciding to perform another effect.

Primary sources

PostgreSQL: INSERT and conflict handlingStripe: idempotent requests

References checked 11 September 2026.