| Users | Requests per Second | Concurrent Bookings | Database Load | System Changes |
|---|---|---|---|---|
| 100 users | ~10-50 RPS | ~5-10 concurrent | Low, single DB instance | Simple locking, basic availability checks |
| 10,000 users | ~1,000 RPS | ~200-300 concurrent | Moderate, DB nearing capacity | Introduce caching, connection pooling, read replicas |
| 1,000,000 users | ~50,000 RPS | ~5,000 concurrent | High, DB bottleneck likely | Sharding, distributed locking, queueing for concurrency control |
| 100,000,000 users | ~5,000,000 RPS | ~500,000 concurrent | Very high, multiple DB clusters | Global distribution, advanced concurrency control, event sourcing |
Why booking tests availability and concurrency in LLD - Scalability Evidence
Start learning this pattern below
Jump into concepts and practice - no test required
The database is the first bottleneck because booking tests require checking and updating availability atomically to avoid double bookings. As concurrency grows, locking and transaction conflicts increase, causing delays and failures.
- Horizontal scaling: Add more application servers behind load balancers to handle more concurrent requests.
- Database read replicas: Offload read queries to replicas to reduce load on the primary DB.
- Caching: Cache availability data to reduce DB hits, with short TTL to keep data fresh.
- Sharding: Partition booking data by region or test center to reduce contention.
- Distributed locking or optimistic concurrency: Use Redis or Zookeeper to manage locks or version checks to prevent double bookings.
- Queueing: Serialize booking requests in a queue to control concurrency and avoid conflicts.
- Event sourcing: Use event logs to track bookings and rebuild state, improving consistency at scale.
- At 10,000 users: ~1,000 RPS -> DB must handle ~1,000 writes/reads per second.
- Storage: Each booking record ~1 KB, 1M bookings = ~1 GB storage.
- Bandwidth: Assuming 1 KB per request/response, 1,000 RPS = ~1 MB/s network usage.
- Concurrency control adds latency; expect 50-100 ms per booking transaction at scale.
Start by identifying the critical resource (database) and why concurrency causes issues. Discuss how availability checks must be atomic to prevent double bookings. Then explain scaling steps: caching, read replicas, sharding, and concurrency control mechanisms. Always justify why each solution fits the bottleneck.
Your database handles 1000 QPS. Traffic grows 10x to 10,000 QPS. What do you do first?
Answer: Add read replicas and implement caching to reduce load on the primary database before considering sharding or more complex solutions.
Practice
Solution
Step 1: Understand concurrency in booking
Concurrency means multiple users try to book the same slot simultaneously.Step 2: Identify the problem caused by concurrency
If concurrency is not handled, multiple users can book the same slot, causing double bookings.Final Answer:
To prevent multiple users from booking the same slot at the same time -> Option CQuick Check:
Concurrency handling = prevent double bookings [OK]
- Thinking concurrency allows unlimited bookings
- Ignoring the need to prevent double bookings
- Assuming concurrency slows down the system intentionally
Solution
Step 1: Understand locking in booking systems
Locking a slot means reserving it temporarily to prevent others from booking it simultaneously.Step 2: Identify when to check availability
Availability must be checked and locked before confirming booking to avoid conflicts.Final Answer:
Lock the slot before confirming the booking -> Option BQuick Check:
Lock before confirm = correct availability check [OK]
- Checking availability after booking causes errors
- Ignoring availability checks leads to double bookings
- Relying on user honesty is not a system design
def book_slot(slot_id):
if is_available(slot_id):
reserve(slot_id)
confirm_booking(slot_id)
return 'Booked'
else:
return 'Unavailable'What issue can arise if two users call
book_slot at the same time for the same slot_id?Solution
Step 1: Analyze the code flow for concurrency
Both users check availability before reservation without locking, so both may see the slot as available.Step 2: Understand race condition effect
Without locking, both reserve and confirm booking, causing double booking.Final Answer:
Both users might get 'Booked' causing double booking -> Option AQuick Check:
Race condition = double booking risk [OK]
- Assuming system crashes automatically
- Thinking both get 'Unavailable' response
- Believing function serializes calls automatically
if check_availability(slot):
book(slot)Users report double bookings. What is the best fix?
Solution
Step 1: Identify the cause of double bookings
Without locking, multiple users can pass availability check simultaneously causing conflicts.Step 2: Apply concurrency control
Using locks or transactions ensures only one booking proceeds at a time for the same slot.Final Answer:
Add a lock or transaction around availability check and booking -> Option AQuick Check:
Locking fixes concurrency issues [OK]
- Removing availability check causes more errors
- Upgrading hardware does not fix concurrency logic
- Telling users to slow down is not a system fix
Solution
Step 1: Understand scalability needs
Thousands of users require a scalable approach that avoids bottlenecks.Step 2: Evaluate locking strategies
Single global lock serializes all requests causing delays; manual fixes cause poor user experience.Step 3: Choose optimistic locking with retries
This approach allows concurrent attempts, detects conflicts, retries, and updates availability promptly.Final Answer:
Use optimistic locking with retries and real-time slot availability updates -> Option DQuick Check:
Optimistic locking + updates = scalable concurrency [OK]
- Using global lock causes slow system
- Ignoring concurrency leads to double bookings
- Manual conflict fixes harm user experience
