# Design E-commerce Checkout and Inventory — High-Level & Low-Level Design Interview Problems

Source: https://www.skillbyai.com/en/design-interviews/checkout

> 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.

```text
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.

**Quiz:** What prevents a retried payment request from charging the customer twice?

- [ ] Sharding the orders table
- [ ] A larger timeout
- [ ] Caching the product page
- [x] An idempotency key sent with the charge

*Answer:* An idempotency key sent with the charge. Same key, same result.
