Design ticketing, payments or ride sharing

12 system design interview questions on ticketing, payments and ride sharing, each with the correct answer and a full explanation.

Ticketing: a user selects a seat and has 10 minutes to pay. If they abandon checkout the seat must become available again. How do you model it?
Show answer

Answer

A hold with an expires_at, treated as free once expired, confirmed on payment
A hold row with an expiry (or a Redis key with TTL) frees the seat automatically and the confirm step checks the hold is still valid. Users who close the tab never click cancel. A daily job leaves seats locked for hours. App memory is lost on restart and invisible to other servers.

Source: Hello Interview: Design Ticketmaster

A concert on sale draws 1 million users for 50,000 seats in the first minute. What keeps the booking system up and fair?
Show answer

Answer

A virtual waiting room that admits users at a controlled rate
A waiting room turns a spike into a steady flow the booking path can handle and gives a fair order. Database autoscaling is slow and contention on the same rows does not scale out. Caching the seat map helps browsing but not 1 million concurrent bookings. Racing on row locks melts the database and is random, not fair.

Source: Hello Interview: Design Ticketmaster, Cloudflare Waiting Room

Design Ticketmaster. Requirements, core entities, API and the deep dives.
Show answer

Answer

  • Requirements: browse and search events, view seat map, book without double booking, handle on sale spikes. Consistency for booking, availability for browsing.
  • Entities: event, venue, seat, ticket, booking.
  • API: GET /events/:id, POST /bookings/hold, POST /bookings/:id/confirm.
  • Deep dive 1, holds: conditional update or Redis lock with TTL, confirm on payment, expire otherwise.
  • Deep dive 2, spikes: virtual waiting room, cached seat map with live updates via SSE.
  • Search: Elasticsearch fed by CDC.

Source: Hello Interview: Design Ticketmaster, Hello Interview: Meta E5 interview guide, Hello Interview: Google L5 interview guide

A wallet system keeps a double entry ledger. Which rule must always hold?
Show answer

Answer

Every transaction's entries sum to zero and entries are never edited, only reversed by new entries
Double entry means each movement debits one account and credits another for the same amount, and the log is append only so history is auditable; corrections are new entries. Updating a balance in place without entries loses the audit trail. Deleting entries destroys history. Recording one side only is single entry bookkeeping.

Source: Accounting for Developers, Part I, System Design Interview: An Insider's Guide, Volume 2

Your call to the payment provider timed out, so your database marked the charge failed. The provider actually succeeded. How do you catch and fix this?
Show answer

Answer

Reconcile with the provider by idempotency key or settlement report and correct your state
A timeout is unknown, not failed. Query the provider (same idempotency key) and run periodic reconciliation against settlement files. A new key creates a second real charge. Providers do not refund on your behalf. External providers do not join your 2PC.

Source: System Design Interview: An Insider's Guide, Volume 2, Designing robust and predictable APIs with idempotency

How should a payments service store the amount 19.99 USD?
Show answer

Answer

As the integer 1999 in minor units, with the currency code
Integers in the smallest currency unit add exactly, which is how Stripe's API takes amounts; note some currencies have zero or three decimals. Binary floats cannot represent 0.1 or 19.99 exactly, so sums drift, and rounding each write does not fix accumulation. Strings with symbols need parsing and lose the currency for symbols like $ shared by many currencies.

Source: Stripe: Supported currencies, zero-decimal and minor units

Checkout calls payment, then inventory, in separate services with their own databases. Payment succeeds, inventory is out of stock. What happens in a saga?
Show answer

Answer

A compensating action refunds the payment
Sagas replace a distributed transaction with local steps and explicit compensations. 2PC across microservices is avoided because it blocks and couples availability. Ignoring it takes money for nothing. Retrying forever leaves the customer charged with no order.

Source: Saga distributed transactions pattern

Design a payment system (Stripe like or a checkout backend). Requirements, flow and correctness guarantees.
Show answer

Answer

  • Requirements: charge once, never lose money, auditability, handle provider timeouts.
  • Flow: create payment intent with idempotency key, call provider, record result, emit event via outbox.
  • Ledger: double entry, append only, balances derived.
  • Correctness: idempotency keys end to end, state machine with unknown state on timeout, reconciliation jobs against provider reports.
  • Failures: retries with the same key, webhooks from the provider deduped, sagas with refunds.

Say explicitly that exactly once delivery does not exist; you get at least once plus idempotency.

Source: System Design Interview: An Insider's Guide, Volume 2, Designing robust and predictable APIs with idempotency, OpenAI system design interview

Drivers update location every 4 seconds; riders query drivers within 2 km. Which index fits?
Show answer

Answer

Geohash or H3 cells in an in memory store, querying the rider's cell and its neighbours
Cell IDs turn a 2D search into a few key lookups and updates are cheap key moves, which suits high churn. A B tree on lat and long can only range on one dimension efficiently. Rebuilding a quadtree in a database per update is expensive. Full scans do not scale.

Source: H3: Uber's Hexagonal Hierarchical Spatial Index, Redis: Geospatial indexes, System Design Interview: An Insider's Guide, Volume 2

A geohash search queries only the rider's own cell and misses a driver 50 meters away. Why, and what fixes it?
Show answer

Answer

The driver is in an adjacent cell; also query the 8 neighbouring cells
Points near a boundary can sit in different cells, sometimes with very different prefixes, so you search neighbours too. A shorter geohash alone still has edges. Geohashes are not random. Staleness is a different issue from a 50 meter boundary miss.

Source: Redis: Geospatial indexes, System Design Interview: An Insider's Guide, Volume 2

1 million active drivers each send a location every 4 seconds. What write rate must the location service handle?
Show answer

Answer

250,000 per second
1,000,000 / 4 = 250,000 updates per second, which is why locations go to an in memory store rather than a durable row per update. 4,000,000 multiplies by 4. 25,000 drops a zero. 1,000,000 assumes one update per second.

Source: System Design Interview: An Insider's Guide, Volume 2

Design Uber's ride matching. Requirements, location ingestion, matching and the deep dives.
Show answer

Answer

  • Requirements: riders request, nearby drivers found in seconds, each driver gets one ride at a time, ETA.
  • Ingestion: drivers push location every few seconds to an in memory geo index (H3 or geohash cells), sharded by region.
  • Matching: query nearby cells, rank by ETA, offer to one driver at a time with a timeout; claim the driver atomically (conditional update or lock with TTL) so no double dispatch.
  • Deep dives: hot cells downtown, surge, driver offline detection, consistency of the trip state machine, payments via the payment system.

Source: System Design Interview: An Insider's Guide, Volume 2, H3: Uber's Hexagonal Hierarchical Spatial Index, PracHub: Uber system design questions

These questions come from the System Design Interview Practice pack in Bertopia.

More system design topics

Practise these on your commute