पाठ 14 / 25

Design E-commerce Checkout and Inventory

Consistency, payments and idempotency.

Placing an order without overselling or double charging

Checkout touches cart, inventory, pricing, payment and orders. Two invariants matter: do not oversell stock and do not charge twice. For inventory, reserve stock with an atomic conditional decrement (UPDATE stock SET available = available - ? WHERE sku = ? AND available >= ?) when the order is created, and release the reservation if payment fails or times out. For payments, send an idempotency key with each charge so retries do not create a second charge; store the order in a PENDING state first and move it to PAID only after the payment provider confirms. Because this spans services, use a saga: a sequence of local transactions with compensating actions (release stock, refund) rather than a distributed transaction. Use an outbox table to publish events reliably alongside the database write.

Checkout saga

Order states and compensations.

POST /orders  (Idempotency-Key: 7f3c...)

1. Order Service    create order(PENDING)             + outbox event OrderCreated
2. Inventory        reserve items (conditional decrement)
                      fail -> order CANCELLED (out of stock)
3. Payment Service  charge(amount, idempotency_key)
                      fail/timeout -> release reservation, order CANCELLED
4. Order Service    order PAID -> ship workflow

Invariants
  available >= 0                      (enforced by conditional update)
  one charge per idempotency key      (provider + our payments table)
  every state change has an event     (transactional outbox)

Reconcile payment status

A payment call can time out after the provider charged the card. Query the provider by idempotency key or rely on its webhook before deciding the order failed.

त्वरित जाँच: What prevents a retried payment request from charging the customer twice?

  • Sharding the orders table
  • A larger timeout
  • Caching the product page
  • An idempotency key sent with the charge
Answer

An idempotency key sent with the charge — Same key, same result.