advanced 2 min answer

A fashion marketplace lets sellers update inventory while customers are checking out. How should reservations, optimistic concurrency, expiry, retries and failed payments interact to prevent overselling?

myntraoversellreservationoptimistic-concurrencycheckout
Show the full answer Hide the answer

The race

Two customers reach checkout for the last unit while a seller simultaneously reduces the count. Three writers, one invariant: stock may not go below zero.

The design that holds

Reserve at add-to-checkout, not at payment. The reservation is a conditional decrement — succeed only if available stock is greater than zero — executed as a single atomic operation on one row. That is optimistic concurrency at the storage layer and it needs no lock manager.

Then:

  • The reservation has a TTL long enough to complete payment and short enough that abandoned baskets return stock quickly. Typically a few minutes, and it is a business decision rather than a technical one.
  • Expiry is enforced by the system, via a sweeper or a TTL in the store, never by the client.
  • Payment failure releases the reservation explicitly, and the release is idempotent because it will be attempted more than once.
  • Payment success converts the reservation into an allocation, and that conversion is idempotent too.
  • A seller's stock reduction cannot invalidate existing reservations. It reduces available stock, which is total minus reserved. If a seller reduces below what is already reserved, that is an exception requiring a business decision, not a silent overwrite.

The modelling choice that makes it tractable

Separate total, reserved and available, and treat available as derived. A single mutable count conflates three facts and makes every concurrent update a conflict. With the split, a reservation and a seller update touch different fields and most of the contention disappears.

The failure everybody hits anyway

Overselling is not fully preventable, because physical stock and recorded stock diverge for reasons that have nothing to do with concurrency — mis-picks, damage, theft, a seller shipping the same unit through another channel. So the architecture needs a defined oversell path: detect at fulfilment, notify, refund or substitute, and record the event so the seller's reliability score reflects it.

A design that assumes overselling can be engineered to zero will handle it badly when it happens, which is more damaging than the oversell itself.