Ticket Reservation Class with 10-Minute Holds, a Four-Ticket User Cap and Expiry Options
Company: Amazon
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
Implement a ticket reservation component for one event with three operations: `hold()`, `buy()` and `available()`. A hold reserves tickets for a user for 10 minutes. If the user buys within that time the tickets are sold; otherwise the hold expires and the tickets become available again. The interview was coded in C++; any object-oriented language is fine.
The report names the three operations but not their signatures. A reasonable starting point is:
```text
hold(user_id, ticket_ids) -> hold_id reserve these tickets for 10 minutes
buy(user_id, hold_id) purchase the tickets of a live hold
available() -> ticket_ids tickets that are neither held nor sold
```
### Clarifying Questions
- Are tickets distinct seats with ids, or interchangeable units counted by quantity?
- Does `buy` take a hold id, a list of tickets or both, and may a user buy tickets they did not hold first?
- Should `available()` return a count or the ids, and does it need to be fast for very large events?
- Is a hold still valid at exactly 10 minutes, and does a later hold by the same user extend an earlier one?
- Is the component called by many threads, or by several servers, at once?
### Part 1 — Holds, purchases and 10-minute expiry
Implement `hold`, `buy` and `available` so that an expired hold is never honored and its tickets reappear in `available()`.
```hint When expiry happens
Decide whether expiry needs a timer at all, or whether it is enough that each operation sees the correct state at the moment it runs.
```
#### What This Part Should Cover
- Ticket states and the transitions between them
- How and when expired holds are released, and the cost of doing so
- A notion of time that tests can control
### Part 2 — A cap of four held tickets per user, and tickets held by others
Follow-up: a single user may hold at most 4 tickets in total across all of their holds. Also handle a request that includes a ticket already held by another user.
#### Clarifying Questions for this Part
- Does the cap count only tickets in live holds, or also tickets the user has already bought?
- If some requested tickets are free and others are held by someone else, should the request fail completely or hold the free ones?
```hint All or nothing
Think about what a user reserving a group of adjacent seats expects when one seat of the group is taken, and which counters must change on every path that ends a hold.
```
#### What This Part Should Cover
- Enforcing the cumulative cap, including when held tickets stop counting
- The policy for partly unavailable requests, and what the caller is told
- Atomicity when two users request the same ticket at once
### Part 3 — Encapsulating the interface
Follow-up: how would you encapsulate the interface so that callers depend only on the operations, not on the internal data structures?
```hint What callers must never see
List what would break for callers if you replaced the in-memory maps with a database, and hide exactly that.
```
#### What This Part Should Cover
- A minimal public interface and a consistent way to report errors
- Which policies and dependencies are injected: hold duration, cap, clock, storage
- Thread-safety as part of the contract
### Part 4 — Other ways to manage expiry
Follow-up: compare other ways of managing hold expiry.
```hint Who notices the deadline
Compare designs in which the reader checks the deadline, a sweeper checks it, or the storage layer enforces it, and ask which of them stays correct if the sweeper stops.
```
#### What This Part Should Cover
- At least two alternatives, with their cost and timeliness
- Behavior with very many holds and with several servers
- Which mechanism correctness relies on, and which only cleans up
### What a Strong Answer Covers
- Clear ticket states and invariants that every operation preserves
- Expiry that is exact as seen by callers, with a testable clock
- The per-user cap and conflict handling, atomic under concurrency
- A small, well-encapsulated interface with injected policies
- A reasoned comparison of expiry mechanisms, including distributed settings
- Tests for the expiry boundary, the cap, conflicts and purchase after expiry
### Follow-up Questions
- The service runs on several servers that share a database. How do you stop two servers from holding the same ticket?
- A client times out and retries `hold`. How do you avoid creating two holds?
- How would you let a user extend a hold, and should extensions be limited?
- How would you test the 10-minute expiry without waiting 10 minutes?
Overview: A low-level design exercise: implement a ticket reservation component with hold, buy and available operations where holds expire after 10 minutes, then cap each user at four held tickets, handle tickets already held by someone else, encapsulate the interface and compare ways to manage expiry.
Read the full Amazon Software Engineer interview experience this question came from