A double click never places two orders

Order creation in The Merchant Engine requires an X-Idempotency-Key. A repeat of the same request with the same key returns the first order instead of placing a second one, stock moves under a guarded update that cannot go negative, and the key is remembered for twenty-four hours.

How it works

The key is required, not optional. A pipe on the route requires the header and validates it as a UUID v4, so a client that forgets it is refused before any order logic runs. The storefront generates the key once when the checkout page is ready and keeps it with the form until the order succeeds.

From the storefront contract in the documentation
// Once per checkout attempt. Keep it with the form until the order succeeds.
const idempotencyKey = crypto.randomUUID();

const response = await fetch(`${API}/v1/orders`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept-Language': locale,
    'X-Idempotency-Key': idempotencyKey,
  },
  credentials: 'include',
  body: JSON.stringify(body),
});

One key, one outcome. Each pair of scope and key is stored in Redis for twenty-four hours with a hash of the caller and a hash of the body. A replay with the same body returns the stored response without running the handler. The same key with a different body is a 409. The same key from a different caller is a 403. A key whose first request is still running reports in flight. When the handler throws, the entry is deleted so a genuine retry can succeed.

Stock cannot go negative. The decrement is a single guarded update that only matches a row with enough on hand, and reports failure when no row changed, so two customers racing for the last unit cannot both win. The same rule covers gift-card balances and promotion usage.

It is not only checkout. Order creation on the customer and the admin side, inventory adjustments and transfers, return refunds, the manual search-engine submission and the webhook test delivery all take the header. Inbound provider webhooks are deduplicated separately, by event id, so a provider that delivers twice is processed once.

Where to read the detail

Questions

What exactly is an idempotency key?

A UUID v4 the storefront generates once when the checkout page is ready and sends on every attempt of that same order as X-Idempotency-Key. The API stores the first answer against the key and replays it instead of running the handler twice.

What happens if the customer taps submit twice?

The second request carries the same key and the same body, so it returns the first order. One order, one stock decrement, one confirmation email.

What if the second request is not the same order?

The same key with a different body is a 409, and the same key from a different caller is a 403. Reusing a key by accident fails loudly instead of quietly overwriting something.

How long is a key remembered?

Twenty-four hours, in Redis, with a hash of the caller and a hash of the body beside it. After that the key is free again.

What happens when the order itself fails?

The stored entry is deleted when the handler throws, so a retry after a real failure can succeed. A key whose first request is still in flight is reported as in flight rather than run twice.

Is it only checkout?

No. Order creation on both the customer and the admin side, inventory adjustments and transfers, return refunds, the manual search-engine submission and the webhook test delivery all require the header. Gift-card redemption runs inside order creation and rides the order’s key.

And if Redis is down?

The request goes through and the database’s unique constraints are the safety net. The engine prefers taking the order to refusing it, and the constraint still refuses a genuine duplicate.

Last updated . Every claim on this page is read from a published source and cited beside it.