1. Courses
  2. System Design
  3. System Design Case Studies
  4. Stop 4

40 minAdvanced

Case study: ordering without overselling stock

On the eve of a big festival, two hundred customers and partner shops want the last fifty cartons of cooking oil, and the payment arrives later from a card or mobile-wallet provider. This case study designs Mangrove Market's ordering so that stock is never sold twice, unpaid holds expire on their own, and every lost message, double tap and crash has a planned answer.

By the end you can

  • Pick a consistency level per piece of data: strong for stock, eventual for the catalogue
  • Reserve stock with one atomic conditional update, all lines or none
  • Model an order as a state machine and enforce it in code and in the database
  • Handle payment webhooks that arrive late, twice, forged or never
  • Fill in a failure table and plan for a festival traffic spike

The everyday picture

Think of the last few pieces of a popular dress at a busy market stall the week before a festival. A customer says "I'll take it". The stallholder does not leave it on the rail while she goes to the cash machine. He puts it behind the counter with a slip: "Held for Mrs Mensah until 7:30". Another customer who asks is told "sorry, that one is held".

If Mrs Mensah pays, the slip says "Paid" and the dress is wrapped. If 7:30 passes and she has not come back, the stallholder tears up the slip and the dress goes back on the rail. If she comes back at 8:00 having already sent the money from her phone, he gives it back, politely, because the dress has been sold to someone else. A hold with a deadline, one person deciding at the counter, and a written rule for every late or confused case: that is this lesson.

Step 1: Requirements

Mangrove's engineers build prepaid ordering for two apps. In the Mangrove app, customers order from their nearest store. In the Partner app, about 1,800 partner shops order stock wholesale from a distribution centre (DC). Both draw on the same stock table: one row per article (a product) per site, where a site is a store or a DC.

Functional requirements.

  • FR1: A buyer places an order for several articles and sees at once whether stock is held.
  • FR2: The buyer pays by card or with a mobile wallet (such as M-Pesa, UPI, bKash or GCash) within 10 minutes. Payment is confirmed by the provider asynchronously, through a webhook and a status query.
  • FR3: An unpaid hold expires on its own, and the stock goes back on sale.
  • FR4: The buyer can cancel before dispatch. A paid order that is cancelled is refunded.
  • FR5: The buyer always sees a clear status: holding stock, paid, on the way, expired.

Non-functional requirements.

  • Never oversell. Units held or sold for an article never exceed the units in stock.
  • Never charge for an order that will not be delivered without refunding it automatically.
  • Placing an order: p95 under 500 ms at festival peak.
  • The catalogue and "in stock" badges may be up to a minute old.
  • Every step is safe to repeat: a double tap, a retried request or a repeated webhook changes nothing.

Non-goals. Splitting one order across several sites, partial delivery, building our own payment gateway, and cash on delivery (it reuses the same reservation but skips the payment step).

Loading the rest of the lesson…