System-design interview · Core interviews
Design a ticket-booking service
Sell exact seats without overselling: separate advisory maps from atomic holds, then handle payment uncertainty and expiry with explicit recoverable states.
You will learn to
- Trace browsing, an all-seat hold, checkout and booking confirmation.
- Resolve conflicting seat requests and payment-versus-expiry races without stealing inventory.
- Scale on-sale traffic with caching and bounded admission while preserving one show authority.
Practice in this chapter
9 interview questions with model answers and follow-ups.
Go to interview practiceUseful foundations: Databases, data models, and ACID transactions · Quorums, consensus, leases, and fencing · Message queues, event logs, delivery guarantees, and backpressure · Caching: cache hits, misses, write policies and invalidation
Workload and timing examples are interview assumptions.
Dotted concept links open the relevant explanation in a new tab.
01Define what buying a seat means
Design exact-seat booking for a show. Customers browse the catalog, view a seat map, hold up to ten selected seats, pay and recover their booking. Exclude resale, auctions and atomic carts spanning several shows. Our running example is show S99: customer A requests seats 54–56 while customer B requests 56–57. Each request gets its whole set or none, and seat 56 cannot belong to both.
A hold is a durable business record reserving seats until a server deadline, such as five minutes. A database row lock is a short concurrency mechanism used while creating or changing that record. Keep the hold for minutes and the transaction for milliseconds; never leave database locks open while a customer enters payment details.
The seat map may lag by two seconds and is advisory. Hold creation targets a 500 ms 95th-percentile latency after admission, with success acknowledged only after the hold is saved under the durability policy explained below. During an unsafe database partition, pause allocation. For payment, allow a bounded processing interval and disclose that a late successful charge may require a refund if the seats have already been released.
Ask whether buyers select exact seats or only a ticket category, whether a cart may span shows, and whether the waiting room must guarantee strict arrival order. This design chooses exact seats within one show and bounded admission without strict first-arrival allocation.
02Functional requirements
Browse a show. List shows and display seat layout, prices and advisory availability.
Hold selected seats. Reserve a requested set of up to ten seats together, returning either the complete hold and its deadline or a conflict.
Pay and confirm. Start payment for an eligible hold, confirm the booking when both payment and seat ownership permit it, and recover a late successful charge through refund handling.
Retrieve the outcome. Let an authorized customer recover hold, payment and booking status after retries or a lost browser response.
03Non-functional requirements
These are illustrative interview assumptions, not product facts or measured benchmarks. Confirm them before choosing components, then validate the completed design under the stated workload. Here p95 means the 95th-percentile latency: 95% of measured requests take no longer than that value. Report errors and rejected work alongside latency; a fast failure is not a successful outcome.
Burst and latency. Plan for 10,000 seat-map reads/s during an on-sale burst. Use 500 admitted hold attempts/s as a load-test assumption and target 500 ms p95 hold creation after admission; waiting-room delay is a separate metric.
Map freshness and hold lifetime. Target advisory seat maps no more than two seconds behind for 99% of normal-load refreshes. Choose a five-minute initial hold and a fixed two-minute processing deadline when checkout begins; a late provider outcome may still need refund recovery.
Inventory consistency. Never allocate one show-seat to two live holds or bookings. A multi-seat request receives every requested seat or none, and expiry cannot release a newer owner’s seats.
Durability and safe failure. Acknowledged holds and bookings must survive one database-node failure under synchronous durable replication and safe failover. Pause allocation when authority is unsafe; payment-provider completion has no unconditional deadline.
Security and retry safety. Authorize hold/status access using the customer or secure guest session. Reuse scoped request and payment identities, verify provider evidence and keep raw card data outside this service.
04Complete the booking flow with one authority
Begin with a booking application, a relational database and an external payment provider. The application serves catalog reads, creates holds, scans deadlines and reconciles pending payments. Background tasks may initially run in the same deployment, but their work must exist durably in the database so a restart can resume it.
Customer A submits seats 54–56 with request key k7. One transaction claims that unique request identity, locks the selected seats in sorted order, checks that all are free and creates hold H7 plus its replay result. If any seat conflicts, the whole transaction rolls back. After commit, A receives the deadline.
At checkout, another transaction verifies H7 and changes it to processing with a bounded deadline. It stores payment attempt P3 and the fixed amount and currency before making the provider call. Provider success is then reconciled with the current hold. If H7 still owns every seat and remains eligible, confirm the booking atomically. Otherwise retain the payment outcome and schedule a refund without reclaiming the seats.
The browser reads booking status to resolve a lost response. A redirect from the payment page is neither proof of payment nor permission to allocate inventory.
The payment call happens after a durable attempt is recorded, outside the seat transaction.
Read each connection in order
- syncBrowse, hold, pay, recover statusCustomer → Booking application
- syncAtomic hold and lifecycle changesBooking application → Seats, holds, payments, outbox
- syncStored payment attempt P3Booking application → Payment provider
- syncFind due or unresolved workExpiry and reconciliation → Seats, holds, payments, outbox
- syncReconcile P3 / refundExpiry and reconciliation → Payment provider
05Size the on-sale burst, not just monthly averages
Assume three billion page views and ten million tickets sold in a thirty-day month. Dividing by 2,592,000 seconds gives roughly 1,157 views/s and 3.86 tickets/s on average. If orders contain two tickets, that is about 1.93 orders/s. These averages conceal the workload that matters: thousands of customers attempting the same show at once.
A burst of 100,000 shoppers opening a show in ten seconds creates 10,000 map reads/s. At 50 KB per response, origin traffic would be 500 MB/s before overhead. A 99% cache hit rate reduces origin requests to about 100/s, although customer-facing edge bandwidth remains.
If a load test supports 500 admitted hold attempts/s at 20 ms mean service time before queuing, roughly ten transactions are active on average. This is an illustrative budget, not a universal database capacity. Waiting on overlapping seat rows can dominate even when CPU is idle.
Store hall geometry once and keep show-specific price and allocation separately. For 20 million show-seat rows/day at 100 bytes each, raw daily inventory is 2 GB. Five years is about 3.65 TB before indexes, replicas and backups; archival policy can keep completed shows out of the hot transaction database.
06Give holds, payments and retries separate identities
Interfaces
| Request or message | Contract |
|---|---|
GET /shows/S99/seats |
Returns layout, prices and advisory availability with an as-of time. |
POST /shows/S99/holds |
Seat IDs, quote version and request key produce one hold or an all-seat conflict. |
POST /holds/H7/checkout |
Starts or recovers the stored payment attempt; may return pending. |
GET /holds/H7/status |
Returns current hold, booking and payment-recovery state to its owner. |
Create the worked seat hold
POST /shows/S99/holds
Hold request values
seat IDs: 54, 55, 56
quote version: the version of the price the customer accepted
request key: k7
Successful hold result
hold: H7
seats: 54, 55, 56
deadline: server-issued hold expiry
Stored records
| Record | Fields or identity | Purpose |
|---|---|---|
| ShowSeat | show, seat, state, holdId |
Current allocation authority for one seat in one show. |
| Hold + HoldSeat | id, owner, state, deadline |
Lifecycle and immutable selected seat set. |
| PaymentAttempt | id, hold, amount, currency, outcome |
Durable identity for an external charge and reconciliation. |
Store request results under show, authenticated session and key, including a payload fingerprint. Retrying k7 returns H7; reusing it for different seats conflicts. Claim the key within the transaction before allocating seats so a duplicate cannot report a conflict against its own first successful request.
Index active holds by state and deadline for expiry, and bookings by owner for recovery. An outbox row records notification or refund work in the same transaction as the business change. A signed-in customer or secure guest session owns the hold; knowing H7 is not sufficient authorization.
07Prove the all-or-nothing seat decision
Keep one show’s seats and holds in a database that can update them together in one transaction. For new hold creation, use one transaction:
Lock requested seat rows in ascending seat ID order.
Check the quote and every current allocation.
Write the entire hold. If the transaction cannot obtain a valid full set, leave no partial reservation.
A wins seats 54–56 first. B's transaction eventually locks seat 56, sees H7 and aborts its request for 56–57. Seat 57 does not remain reserved by B merely because it was free. If B wins first, A fails symmetrically. Unique seat keys and transactional checks protect the actual current allocation; a distributed cache lock is unnecessary for this baseline.
The same lifecycle operations use a consistent order: hold row, its immutable seat set in sorted order, then the payment-attempt row where needed. Re-read state after acquiring locks and handle bounded deadlock retries. Creation may use its own ordered seat lock path because its new hold is not yet visible to other operations.
A deadline is part of validity even if an expiry worker is late. To release a due hold, verify that each seat still belongs to that hold. An old cleanup attempt must never free a seat that now belongs to a newer allocation.
08Resolve the payment and expiry race explicitly
The payment provider and our database do not share one transaction. Before calling the provider, store P3, set H7 to processing and store a fixed deadline two minutes after checkout starts. Retries reuse P3 under the provider's supported idempotency contract. A timeout leaves the outcome unknown, not declined; the service queries the provider or processes verified callbacks for that same attempt.
At confirmation, lock H7 and its seats, check the authoritative database clock after waiting for locks, and require H7 to be processing, unexpired and still owner of every selected seat. Verify the provider account, attempt, successful outcome, amount and currency. If all checks pass, record payment success, booking and booked seats in one transaction. Duplicate success notifications return the existing outcome.
Now pause the provider response until after H7 expires. Expiry releases 54–56; B creates H8 for 56–57. When P3's success arrives, H7 is no longer eligible and seat 56 belongs to H8. Record the successful charge and unique refund work. Do not resurrect H7. B keeps the seats; A sees refund recovery rather than a false booking.
Refund work also needs a stable external identity and reconciliation. Submitting a refund is not proof it completed. An authorization-then-capture provider workflow may reduce this risk, but it still needs a defined policy for uncertain external outcomes.
Expiry and confirmation both recheck current ownership in the same authority.
Read each connection in order
- syncRelease expired H7Expiry worker → Booking database
- syncCreate H8 for seats 56–57Booking API for B → Booking database
- asyncP3 succeeded after delayPayment provider → Success handler
- syncH7 released; seat 56 belongs to H8Success handler → Booking database
- syncRecord payment and unique refund workBooking database → Booking database
- returnNo booking for H7; preserve H8Booking database → Success handler
09Cache browsing and control entry to scarce inventory
Move catalog, static hall geometry and short-lived seat maps behind caches when read bursts dominate. Include map timestamps and avoid caching personalized hold status as public content. Collapse concurrent cache refreshes so an expired popular map does not send thousands of identical database reads.
Bound hold attempts before they occupy database connections. A waiting room or admission service issues short-lived grants; the hold transaction validates and consumes a grant if admission is active. Rate-limit seat hoarding by account/session and risk signals. Admission limits simultaneous work; it cannot increase the number of seats for sale.
For the interview baseline, promise bounded admission and explain the fairness policy without claiming strict first-arrival seat allocation. Several simultaneously admitted customers can still race, and network timing affects who commits first. A strict first-in-first-out policy requires durable waiting order and tighter grant sequencing, trading utilization and throughput for stronger fairness.
Partition independent shows when aggregate storage or writes exceed one database. Sharding by show keeps the seat-set transaction local; sharding by movie unnecessarily combines many performances of a blockbuster. One very hot show still sends competing allocations to the same inventory database. More web servers do not remove that shared-seat conflict.
Admission bounds requests before booking transactions compete for seats. The booking API uses cached catalog data for browsing but commits holds and bookings in the show database. Payment workers load stored attempts, call the provider and reconcile results against the same hold authority; callbacks enter that recovery path too.
Read each connection in order
- syncBrowse / booking statusCustomer → Booking API replicas
- syncHold requestCustomer → Admission service
- syncAdmitted request and grantAdmission service → Booking API replicas
- syncAdvisory browse readsBooking API replicas → Catalog and seat-map cache
- syncAtomic hold / bookingBooking API replicas → Show inventory / booking DB
- syncLoad work / apply transitionsPayment and expiry workers → Show inventory / booking DB
- syncStored payment operationPayment and expiry workers → Payment provider
- asyncVerified callbackPayment provider → Booking API replicas
- returnHold or booking statusBooking API replicas → Customer
10Keep cleanup, notifications and failover recoverable
Expiry workers scan the durable deadline index in bounded batches. They perform the same guarded transitions as interactive operations, so restarting a worker or processing a deadline twice is safe. Cleanup may delay availability, but cannot extend the validity of an expired hold. Payment reconcilers scan unresolved attempts independently of browser activity.
The outbox drives map invalidation, booking notifications and refund work. Delivery may duplicate or arrive late. Events include booking versions, and the client retrieves current status after a gap rather than treating arrival order as state order. A notification outage can delay user awareness without undoing a booking.
Use synchronous durable replication of the authoritative database to meet the promised one-node failure tolerance. Safe failover must preserve acknowledged holds and stop the old primary from accepting writes. Changing DNS does not prevent the old primary from continuing to write. During uncertainty, show waiting or temporary failure rather than a reservation that was never safely committed.
Backups protect against deletion and corruption that replication repeats. Restore a test show, compare seats, holds, payment attempts and replay results, and reconcile external payments before resuming allocation. A restored inventory table alone does not establish which provider charges remain unresolved.
11Measure correctness, contention and recovery age
Monitor admitted hold latency, lock wait, transaction aborts, active-hold age, map freshness, queue delay and provider-unknown backlog. Track the oldest unresolved payment and refund, not just their counts. A single forgotten charge can be important even when aggregate checkout success looks healthy.
Run invariant checks for duplicate seat allocations, confirmed holds missing selected seats and inconsistent booked states. Test overlapping seat sets, duplicate request keys, worker crashes before and after commit, delayed success after expiry and a callback arriving twice. Stop expiry workers deliberately: holds should become invalid at their deadlines even though free-seat cleanup is delayed.
Verify webhook signatures on the raw provider payload and validate the event against the stored attempt. Keep card data with the provider and store tokens or references. Protect hold/status endpoints against guessing and unauthorized cancellation. A secure guest session needs the same ownership checks as a registered account.
For upgrades, deploy readers that understand a new lifecycle state before enabling writers that create it. Roll out to a small group of shows and retain a rollback path that understands already-created records. Correctness depends on every writer respecting the same transitions, not merely on the newest checkout endpoint.
12Check the design against its requirements
Use the numbered requirements to check the final design. FR refers to the functional list; NFR refers to the non-functional list. Performance rows specify tests still required, not achieved benchmark results.
| Requirement | Design mechanism | Verification and remaining limit |
|---|---|---|
| FR1; NFR1–2: browse under a burst | Cache geometry and timestamped advisory maps, with collapsed refreshes. | Generate 10,000 reads/s and measure map age. Cached green seats must never be treated as reservations. |
| FR2; NFR1,3: atomic seat holds | Lock the selected rows in a stable order and commit hold, deadline and replay result together. | Race seats 54–56 against 56–57; assert whole-set outcomes and load-test admitted p95 latency under overlapping-seat contention. |
| FR3; NFR2–3: payment versus expiry | Persist one payment attempt, recheck current ownership/deadline at confirmation and create unique refund work for ineligible late success. | Delay P3 beyond the processing deadline, allocate seats to H8 and deliver P3 twice. H8 keeps the seats; refund recovery remains visible. |
| FR4; NFR4–5: recover a protected booking | Authoritative status, durable replay/outbox records and safe database failover. | Lose responses, fail the primary and attempt another session’s status request. Recover the same booking, preserve seat ownership and deny unauthorized disclosure. |
13Rapid revision
Remember: The map suggests availability; the transaction reserves seats. A late charge cannot take seats from a newer hold.
| Topic | Mechanism and limit |
|---|---|
| Browse | Cache catalog and advisory maps; a green seat is not reserved. |
| Hold | Lock and validate every selected seat in one short transaction; save the hold and its deadline. |
| Retry | Scope the key to the show and authenticated session; save the request and result so a retry returns the same hold. |
| Checkout | Persist processing state and one payment attempt before the external call. |
| Confirm | Verify payment; lock and recheck the hold, deadline and ownership of every seat before booking. |
| Expire | Release only seats still owned by the expired hold; delayed cleanup does not extend validity. |
| Late payment | Record the charge and retryable refund work; never reclaim a newer customer's seats. |
| Scale | Cache reads, limit admitted requests and separate shows across shards; one popular show still has competing buyers. |
| Recover | Resume saved work, prevent former owners from writing, and check uncertain payments with the provider. |
Close by tracing A's seats 54–56, B's conflicting 56–57, and P3 arriving after expiry. This demonstrates the actual design more clearly than listing databases, queues and caches. State that strict waiting fairness and multi-show atomic carts are stronger contracts requiring additional coordination.
14Optional prompt variant: reserve every night of a hotel stay
This is an alternative interview prompt: reserve hotel rooms across several nights instead of seats for one performance. Keep the main ticket-booking design unchanged. The new difficulty is that a stay consumes capacity on every occupied night, and a shortage on one night invalidates the whole request.
Model inventory by (hotelId, roomType, localDate), with capacity, held quantity and booked quantity. Available quantity is capacity − held − booked. The room type promises a category such as a standard double; assigning a particular physical room is a separate hotel operation. Use hotel-local calendar dates and the interval [checkIn, checkOut): checkout day consumes no night. Reject invalid dates, excessive stay lengths and missing inventory rows rather than guessing their capacity.
A guest requests one standard double from November 5 through November 8. The occupied nights are November 5, 6 and 7:
| Night | Available before this request | Can reserve one? |
|---|---|---|
| November 5 | 2 | Yes |
| November 6 | 0 | No |
| November 7 | 3 | Yes |
The result is rejection of the whole stay. No hold remains on November 5 or 7. Reserving each night in a separate committed transaction would instead leave the guest with an unusable partial booking.
Keep each hotel’s inventory in one database transaction scope. Reserve the stay as follows:
Authenticate the guest. In the reservation transaction, claim a stable request identity with a fingerprint covering hotel, room type, dates, quantity, price and currency.
Lock all required nightly inventory rows in increasing date order.
Confirm that every row exists and has sufficient available quantity.
If all checks pass, increase held quantity on every night and create one reservation with its nightly allocations, server-issued expiry and replay result in the same commit.
Browsing a cached availability calendar does not reserve anything.
Use the existing bounded payment-processing flow without keeping inventory locks open during provider calls. Confirmation locks the reservation and its nightly rows, rechecks its current eligibility and atomically changes every allocation from held to booked. Expiry or permitted cancellation changes reservation state and releases the corresponding quantities together. Each transition checks the prior state, so duplicate workers cannot release or confirm the same capacity twice. A late payment success cannot reclaim nights already released; recover the financial outcome through the stated refund policy.
Test two overlapping stays, a missing middle-night row, an expired hold after lock waiting, a lost commit response and two expiry workers. PostgreSQL’s row-lock and deadlock guidance supports the concrete transaction mechanism. Multi-hotel packages spanning independent databases need a separate reservation workflow; this example promises one hotel’s all-night atomic reservation.
Practise the interview questions
Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.
Why distinguish a hold from a row lock?
Reveal a model answer
A hold is a durable reservation with a business deadline. A row lock protects a short state transition; holding it while a person pays wastes connections and does not define recovery.
Interviewer follow-up
What if cleanup stops?
Reveal the follow-up answer
The deadline still makes the hold invalid; cleanup only restores availability promptly.
What the answer must demonstrate: Distinguish minutes-long business reservations from short database locks.
How do seats 54–56 and 56–57 avoid a partial allocation?
Reveal a model answer
Each transaction locks its selected seats in order, validates the full set and commits all changes together. The loser on seat 56 rolls back its entire set.
Interviewer follow-up
Would atomic updates on individual seats suffice?
Reveal the follow-up answer
No. They might leave a customer holding only some requested seats.
What the answer must demonstrate: Validate and commit the entire requested seat set or roll it back.
The hold response disappears after commit. What next?
Reveal a model answer
Retry the same scoped key and payload to retrieve the saved hold. Claim that key before allocation so concurrent duplicates serialize correctly.
Interviewer follow-up
What if the payload changes?
Reveal the follow-up answer
Reject the key reuse; it is a new logical operation, not a retry.
What the answer must demonstrate: Claim a scoped request identity and compare payloads before allocating seats.
A payment times out. Can the customer be charged again?
Reveal a model answer
Not merely because of the timeout. Reuse the stored attempt identity and reconcile its outcome under the provider contract.
Interviewer follow-up
What must precede the provider call?
Reveal the follow-up answer
A durable attempt, amount/currency and bounded processing state for the hold.
What the answer must demonstrate: Persist a stable attempt before the provider call and retain unknown outcomes.
Payment success arrives after another customer holds the seats. What happens?
Reveal a model answer
The success transaction finds the old hold ineligible and records refund work without changing the new allocation.
Interviewer follow-up
Why check again after payment?
Reveal the follow-up answer
Expiry or cancellation can change ownership during the external call.
What the answer must demonstrate: Recheck hold eligibility and ownership; compensate without reclaiming another hold’s seats.
Does a waiting room guarantee first-arrival seat allocation?
Reveal a model answer
No. Several admitted clients can race and network timing can reorder their commits. State whether the product promises bounded load or strict fairness.
Interviewer follow-up
What does strict fairness cost?
Reveal the follow-up answer
Durable ordered grants and less concurrency, with possible head-of-line blocking.
What the answer must demonstrate: State the chosen admission fairness contract and its concurrency cost.
Why partition by show?
Reveal a model answer
Customers compete for seats within one show. Keeping those seats together lets each hold commit atomically, while different shows scale independently.
Interviewer follow-up
Does it solve one extremely popular show?
Reveal the follow-up answer
No. Cache browsing and control admission to that show’s authority.
What the answer must demonstrate: Keep a show’s seat set local while recognizing the single-show contention limit.
Why are three database replicas not a complete durability answer?
Reveal a model answer
The commit and promotion policies determine whether acknowledged holds survive and whether old writers are fenced. Replica count alone says neither.
Interviewer follow-up
What is the safe response during uncertainty?
Reveal the follow-up answer
Pause new allocations and preserve recovery/status paths rather than accept conflicting writes.
What the answer must demonstrate: Name acknowledgment, safe promotion and old-writer fencing instead of counting replicas.
How does the design change when the booking is a three-night hotel stay?
Reveal a model answer
Inventory becomes a room-type capacity row for every occupied hotel-local date in [checkIn, checkOut). One transaction checks and reserves all nights. If the middle night is unavailable, reject the entire stay with no partial holds. Confirmation or release changes every nightly allocation and the reservation state atomically.
Interviewer follow-up
Does booking each night in a separate successful transaction preserve this contract?
Reveal the follow-up answer
No. It can commit the first and third nights while the second fails, leaving a partial stay. Keep one hotel’s night rows in the same transaction domain, or explicitly choose a more complex pending reservation workflow across independent owners.
What the answer must demonstrate: Identify room-type/date inventory, exclusive checkout date, whole-stay atomicity and duplicate-safe hold transitions.
Blank-page exercise · 45 minutes
Build the answer yourself
Design exact-seat booking, then delay a successful payment until the old hold expires and another customer acquires one of its seats.
- Agree numbered functional and non-functional requirements, including exact-seat scope, admission latency and hold/payment deadlines. Then trace browsing, an all-seat hold, checkout and booking confirmation.
- Resolve conflicting seat requests and payment-versus-expiry races without stealing inventory.
- Scale on-sale traffic with caching and bounded admission while preserving one show authority.
- Trace a timeout and a concurrent request using the actual durable records.
- Review the final architecture against every numbered requirement, including measured bottlenecks, targets still needing validation and remaining failure limits.
Check that each component and design decision follows from your requirements and workload.
Recall the key ideas
Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.
Design a ticket-booking serviceA wants seats 54–56 and B wants 56–57. What happens if A’s hold commits first?Recall first, then reveal
B finds seat 56 owned by A and rolls back the entire request, including seat 57. The cached map cannot override that committed hold.
A shared seat creates a conflict: reserve the whole set or none.
Return to lessonDesign a ticket-booking serviceWhat does a payment timeout mean?Recall first, then reveal
The provider may have charged already. Recover the result of the same payment attempt.
Unknown is not declined.
Return to lessonDesign a ticket-booking servicePayment succeeds after the seats were released. What happens?Recall first, then reveal
Save and retry the refund work; never take seats from a newer hold.
Refund the late charge; keep the newer customer’s seats.
Return to lessonFinal revision
Summary and interview notes
Reserve all selected seats in one transaction; the displayed seat map is only a guide. Save payment progress, enforce hold expiry, and recover uncertain charges without taking another customer’s seats.
Remember these points
- Reserve a complete seat set in one short transaction.
- Make retries return the committed hold.
- Persist and reconcile external payment attempts.
- Refund a late successful charge without taking seats from their newer owner.
Interview tips
- Keep the hold deadline separate from short database locks.
- Race 54–56 against 56–57, then deliver payment success after the winning hold expires.
Important qualifications
- Traffic and latency figures are interview assumptions, not claims about a named company's deployment.
Continue after the core interview
Explore the advanced version
The advanced lesson keeps the full detailed design. Use these sections when you want to examine the stronger requirements and failure cases.
- Strict waiting fairness
Durable first-in-first-out admission is a stronger contract than bounded concurrent admission.
- Full confirmation-versus-expiry proof
Inspect deadline clocks, lock ordering and every permitted payment transition.
- Shard and coordinator recovery
Fenced coordinator epochs and restored waiting order matter for stronger admission designs.
- Multi-show carts
Atomic sets across shows require a new distributed transaction or compensation contract.
Technical references
- PostgreSQL explicit lockingExplains row locks, conflicts, and deadlock considerations for short reservation transactions.
- Stripe idempotent requestsProvider-specific retry contract; business retention/reconciliation must still be designed.
- Stripe webhook event handlingDocuments signature verification, duplicate events and non-guaranteed delivery ordering; application reconciliation remains necessary.
- PostgreSQL INSERT and conflict handlingSupports unique request claims and conflict-aware insert behavior; the booking transaction still defines all-seat atomicity.
- PostgreSQL current date/time functionsExplains why deadline validation after a lock wait cannot rely on transaction-start now().
Practice marks stay in this browser.