MongoDB from Basics to Production · Capstone
Capstone: Design the Data Layer for Event Ticketing
Design MongoDB collections, indexes, consistency and operations for a ticketing platform with flash sales and seat reservations.
Scenario
A ticketing platform sells seats for concerts. Popular events sell out in minutes: tens of thousands of fans try to reserve seats at once. Reservations hold seats for 10 minutes until payment; unpaid holds must be released. Organisers see live sales dashboards, and fans see their tickets and order history.
Requirements
- No seat is ever sold twice.
- Held seats are released automatically after 10 minutes.
- Fans' "my tickets" page is fast; organisers' dashboards update within seconds.
- The system survives a database node failure without losing paid orders.
Constraints
- MongoDB replica set (three nodes); Python services; about 500 events per month, up to 80,000 seats per event.
Deliverables
- Collections and document design.
- Seat reservation without double booking.
- Indexes.
- Expiring holds and dashboards.
- Durability and operations.
Hints
- Single-document atomic updates are your best friend.
- Think about which documents get hot during a flash sale.
Draft each deliverable below before revealing the model answer and rubric.
Further reading: Data modeling · Transactions
Deliverables
Describe the collections and document design.
Model answer
events(details, venue, sale times),seats(one document per seat: eventId, section, row, number, statusavailable|held|sold, holdId, heldUntil),orders(fan, event, seats copied with price at purchase, payment status),fans.- Seats as individual documents (not one array per event) so updates don't contend on one huge document and arrays stay bounded.
- Orders embed the purchased seats (historical copy) for a fast "my tickets" page.
Rubric
Look for per-seat documents to avoid a hot, unbounded event document, and embedded historical data in orders.
How do you reserve seats without double booking?
Model answer
- Atomic conditional update per seat:
updateOne({_id, status: "available"}, {$set: {status: "held", holdId, heldUntil}}); ifmodifiedCountis 0, the seat is taken. - Multi-seat requests: reserve seat by seat and release the ones already held if any fails (or a short transaction over the seats, with retries on write conflicts).
- Payment confirmation:
updateMany({holdId, status: "held"}, {$set: {status: "sold"}})plus the order insert in a transaction; idempotency key on the payment webhook.
Rubric
Strong answers use conditional atomic updates (compare-and-set) rather than read-then-write, with a clear plan for multi-seat holds and idempotent payment.
Which indexes do you create?
Model answer
seats:{eventId: 1, status: 1, section: 1}for availability maps;{holdId: 1}for confirmations;{status: 1, heldUntil: 1}for releasing expired holds.orders:{fanId: 1, createdAt: -1}for "my tickets"; unique{paymentId: 1}for idempotent webhooks.- Verify with explain under realistic data; avoid extra indexes on the hot seats collection.
Rubric
Look for indexes matching each access pattern (ESR order), uniqueness for idempotency, and restraint on write-heavy collections.
How do you expire holds and feed dashboards?
Model answer
- A worker releases holds every few seconds:
updateMany({status: "held", heldUntil: {$lt: now}}, {$set: {status: "available"}, $unset: {holdId: "", heldUntil: ""}}). TTL indexes delete documents, so they don't fit status changes. - Dashboards: a change stream on
ordersandseatsupdates per-event counters (pre-aggregated documents) and pushes to organisers via WebSockets; store resume tokens.
Rubric
Strong answers notice TTL deletes documents (unsuitable for status resets), use a precise release job, and drive live dashboards from change streams with pre-aggregation.
How do you ensure durability and operate the system?
Model answer
w: "majority"for orders and sold seats; retryable writes on;readConcern: "majority"for confirmations.- Load-test flash sales; monitor operation latency, write conflicts, replication lag and connection counts; scale reads for event pages with caching.
- Backups with point-in-time recovery; schema validation on orders and seats; alert when holds aren't released.
Rubric
Look for majority write concern on money paths, load testing of the hot path, observability, and backups with point-in-time recovery.
Open in the app to mark lessons complete, take notes and track your progress.