पाठ 12 / 25

Inbox, Idempotency Keys and Exactly-Once Illusions

Combine the inbox pattern and idempotency keys to make end-to-end processing safe.

Safety on the receiving side

The inbox pattern is the consumer-side twin of the outbox: on receipt, store the message ID (and often the message) in an inbox table in the consumer's database, in the same transaction as the business change, and skip IDs already present. When a consumer calls an external API with side effects, such as a payment gateway, pass an idempotency key derived from the event (for example the event ID or orderId:attempt); well-designed APIs, including major payment providers, return the original result instead of charging twice when they see the same key. Together, outbox + at-least-once broker + inbox/idempotent consumer + idempotency keys give the practical effect of exactly-once processing. Remember also that some side effects cannot be made idempotent (an SMS already sent); for those, accept rare duplicates or add a check before acting.

Calling a payment API with an idempotency key

A retry with the same key returns the original charge rather than creating a new one.

import requests

def charge_for(event):
    order = event["data"]
    resp = requests.post(
        "https://payments.example.com/v1/charges",
        json={"amount": order["totalMinor"], "currency": order["currency"],
              "reference": order["orderId"]},
        headers={"Idempotency-Key": f"charge-{order['orderId']}"},
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()["chargeId"]

Derive keys from the business fact

A random UUID per attempt defeats the purpose. Base the key on something stable, such as the order ID, so every retry of the same intent produces the same key.

त्वरित जाँच: Which combination gives effectively-once processing in practice?

  • Outbox publishing, at-least-once delivery and idempotent consumers
  • At-most-once delivery and no checks
  • Synchronous calls with retries and no keys
  • Two brokers in parallel
Answer

Outbox publishing, at-least-once delivery and idempotent consumers — Reliable publishing plus deduplicating consumers turns duplicates into no-ops.