Capstone Pass 1: The Marketplace MVP
The Brief
You've met this moment before — as a reader. Now it's yours.
"Plates" is a food-delivery marketplace launching in one metro in 8 weeks. 4,000 restaurants have signed. Customers browse restaurants and menus, order and pay; restaurants accept; customers watch their order's status. The launch target the business signed off: 500K DAU, about 40 requests per user per day (browsing is most of it), roughly 4% ordering on a given day → 20K orders/day. Menus change a few times daily. Food traffic has two sharp meal spikes — earn the top of the peak rule.
Your deliverable is Pass 1 from the capstone map: the single-region MVP — the correct one box, grown just enough. API behind a load balancer, a cache where it pays, a queue where it pays, one honest database, and the load estimate that justifies all of it.
The one rule from the trailhead still stands: attempt before you peek. Grab paper. Sketch your own boxes and arrows and run your own envelope before the guided build below — the build will grade your instincts decision by decision, and the reference design afterward is for comparing, not copying. A rough draft you correct teaches more than a clean answer you read.

Build It: Seven Decisions
Design reviews run in an order, and the order is the method: cut scope → run the envelope → size the topology → settle the read path → settle the write path → home the data → name the exits. Seven decisions below, in exactly that order. Three are traps three ways — every wrong option is a mistake this container taught you to see coming. The envelope stage takes your own numbers, free-typed, checked within 2×.
Watch the canvas as you go: your system draws itself, one decision at a time — and when the last decision lands, watch the dinner rush actually flow through it.

The Reference: The Cut and the Numbers
Compare, don't copy. Here's the reference reasoning for the first two decisions, in the words you'd say at the whiteboard.
The cut. Live courier GPS goes. Not because it isn't valuable — because it's a real-time fan-out system disguised as a feature: persistent connections from every waiting customer, a location stream from every courier, and a fleet of edge cases (tunnels, dead batteries) — a Pass-3-sized problem hiding in a launch list. Status polling ("preparing → out for delivery") covers the actual customer need with a boring GET. Meanwhile payment stays, because a marketplace that can't take money is a directory; and restaurant accept stays, because a confirmed kitchen is the product promise. Scope discipline isn't cutting what's hard — it's noticing which hard things have boring substitutes.
The envelope. 500K × 40 = 2×10⁷ requests/day. Divide by 10⁵: 200 QPS average. Meal spikes take the top of the rule: ×5 → 1,000 QPS peak. Now the write side: 20K orders/day is 0.2 orders/second — call it 1/second at dinner. Sit with that asymmetry for a moment, because it's the whole design: a marketplace is a huge read product wrapped around a tiny, precious write core. A thousand QPS of browsing that tolerates minutes-stale menus; one order per second that tolerates nothing. Storage tells the same story: menus ≈ 240 MB (4K restaurants × 60 items × 1 KB — megabytes!), photos ≈ 50 GB, orders ≈ 45 GB/year replicated. Nothing here scares a single database for years — and saying that out loud, with the numbers, is what separates an estimate from a vibe.

The Reference: The Architecture
Topology. 1,000 peak QPS against app servers comfortable at ~500: two would run at 100% — on the cliff side of the utilization knee, with zero redundancy at the exact minutes that matter. Three to four stateless servers behind the LB: every box under the knee, dinner survives losing one, and the LB can spray requests freely because state lives in the database and cache (the §3 contract). Band 2–3 on the map, which is exactly what the envelope said to build.
The read path. ~950 of the 1,000 peak QPS is customers re-reading the same 4,000 menus — repetition is locality, and locality is what a cache bets on. Cache-aside, TTL ~5 minutes: menus change a few times a day, so minutes-stale is invisible; the entire menu corpus is 240 MB, so it fits in one cache node's RAM with room to spare; and the meal-rush flood dies in the cache instead of burning the primary's headroom. Order status, by contrast, stays uncached — per-user, read twice, changing constantly: no locality, no bet.
The write path. The order request keeps only what must be true before saying "ordered!": validate, charge, persist — synchronous, transactional. Everything that needs to happen soon but not now — notify the restaurant, assign a courier, email the receipt — goes onto the queue for workers: retryable, burst-absorbing, invisible to the customer. At ~1 order/second the queue is frankly bored; it's there for the shape (the money path never waits on an email server) rather than the volume. That asymmetry — sync for the precious, async for the eventual — is §7's entire argument, deployed.
The data. One PostgreSQL holds users, restaurants, menus, orders — the whole relational footprint is megabytes-to-gigabytes, and one well-backed-up primary carries it for years. The photos live in object storage behind the CDN, and the database keeps pointers — the exact blob/metadata split the photo-app walkthrough derived. No shards (a one-way door bought against a ceiling ~100× away), no polyglot persistence (three sources of truth for a dataset that fits in RAM), no images-in-the-DB (the backup that took minutes now takes hours).
The exits, named. Reads 10× → band 3: grow the cache, add read replicas — an afternoon each. Writes have ~100× of headroom before the primary's ceiling is a conversation. Geography — a second metro, then a second region — is Pass 3's problem, and pretending otherwise today would cost the launch. Build for now, design for 10×, sketch 100×.

Grade Yourself: The Pass 1 Rubric
Score your paper attempt (not the guided build — your sketch before it) honestly. One point each:
The numbers (4):
- Stated your assumptions out loud before computing anything
- Ran per-day → per-second with ÷10⁵ (or 86,400 — either, deliberately)
- Applied a peak multiplier — and said why food earns the top of the range
- Noticed the read/write asymmetry (~1,000 QPS reads vs ~1/s orders) and said what it implies
The shape (5):
5. Cut a real feature — and defended the cut
6. Sized the fleet from your own peak number with knee + redundancy reasoning (not a guess)
7. Cached the menus with a TTL — and left order status uncached
8. Kept charge/persist synchronous and pushed the fan-out through a queue
9. One relational database defended with sizes; images in object storage behind the CDN
The judgment (3):
10. Nothing in the design exists without a number or a failure mode justifying it
11. Named the next ceiling and the lever (reads → cache/replicas), without pre-building it
12. Could say all of this out loud in ~10 minutes to another engineer
10–12: staff-shaped. The Pass-5 interview run will feel like a formality. 7–9: solid pass — reread the reference for whichever tier dropped points. Below 7: genuinely fine — this was your first blank sheet; reread The Reference above against your sketch, note the three biggest gaps in the margin, and redo the sketch tomorrow from memory. The second attempt is where Pass 1 actually locks in.
What Pass 2 Will Break
This design is correct — and it's carrying quiet debts that growth will call in. A preview of the cracks, because seeing them now is what makes the data course land later:
- The last pizza problem. Two customers order the final margherita in the same second. Today: two rows both say 'confirmed.' Pass 2 opens with inventory truth under concurrency — transactions, isolation, and what 'correct' costs.
- Search. "Best sushi near me under ₹500" is a LIKE-query nightmare brewing; menus will outgrow
WHERE name ILIKE. Access patterns will demand their own shapes. - Order history forever. 45 GB/year is fine… until analytics wants three years of it fast while the same table serves tonight's dinner rush. Hot and cold data will want different homes.
Notice none of these are load problems — the envelope's exits already cover load. They're data problems: correctness, access patterns, growth. That's precisely the next container.
Container 1, Closed: The Toolbox You Leave With
Look back at what your seven decisions quietly used: the client-server contract and what HTTP actually carries; why the second server exists (availability, not speed) and why it had to be stateless; what a load balancer does and what it costs; the cache bet and when it pays; sync versus async and which work deserves which; a database trusted with the precious writes; a CDN doing what geography demands; and a ninety-second envelope that told you how much of everything to build — plus the band map that told you when to stop.
That's Container 1, in operation. You didn't recite it; you spent it on a blank sheet — which was the entire promise of the fundamentals course: not to know the pieces, but to reach for the right one, sized right, without ceremony.
Next: Container 2 — Data Systems. The marketplace you just launched starts growing, and its data starts asking the hard questions: the last pizza, the search box, the three-year order history. Bring this design with you — every pass builds on the one before, and Pass 2 starts exactly where your PostgreSQL primary is standing.