What idempotency means

An operation is idempotent when its result does not change with the number of times it runs. The standard example: assigning a value to a variable (x = 5) is idempotent — run it a hundred times and the result is the same. An increment (x += 1) is not.

In APIs and distributed systems, idempotency is the guarantee that makes a retry after a failure safe:

# An idempotent request - PUT
PUT /cart/items/SKU-1234
{ "quantity": 2 }
-> A repeat gives the same result: quantity = 2

# A non-idempotent request - POST
POST /cart/items
{ "sku": "SKU-1234", "quantity": 2 }
-> A repeat creates a second line: quantity = 4

Why it matters in e-commerce

In an online store every request travels a chain: browser to CDN to API gateway to backend to database. That chain produces timeouts, dropped connections and repeat requests. Without idempotency:

  • Duplicate orders: the shopper pressed Buy, the response never arrived, the browser repeated the request — and a second order was created.
  • Double charges: the payment gateway received a retry and processed the transaction twice.
  • Distorted analytics: a purchase or add_to_cart event was counted several times.

The idempotency key in practice

The standard pattern: the client generates a UUID for each operation and passes it in a header.

POST /orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{ "cart_id": "abc123", "payment_method": "card_xxx" }

The server stores (idempotency_key -> response) with a TTL, usually 24 to 48 hours. On a repeat request with the same key it returns the cached response without running the operation again.

Important: the idempotency key TTL must be long enough to cover the typical retry window — usually a few minutes. But not forever, or the store grows without bound.

Idempotency in personalization platforms

For recommender systems and A/B testing two aspects matter:

Scenario Risk without idempotency Fix
Event API (view, purchase) Duplication inflates the product’s weight in the profile Deduplicate by event_id within a time window
Conversion event in an A/B test One transaction counted twice in the metric A unique constraint on (test_id, user_id, order_id)
User profile update Surplus data distorts segmentation PUT instead of POST for updates

Common integration mistakes

  • Using POST instead of PUT to update entities — that makes the operation non-idempotent by design
  • Not passing an idempotency key on payment operations
  • Handling retries in client code with no deduplication on the server
  • Leaving event_id out of the tracking event schema — adding it later without a migration is hard