Bird
0
0
LLDsystem_design~7 mins

Reservation and hold system in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
When multiple users try to book the same limited resource simultaneously, conflicts arise causing double bookings or lost reservations. Without a mechanism to temporarily lock or hold resources, users may experience frustration due to inconsistent availability and failed transactions.
Solution
This pattern introduces a temporary hold on resources when a user initiates a reservation, preventing others from booking the same resource during the hold period. If the user completes the booking within the hold time, the reservation is confirmed; otherwise, the hold expires and the resource becomes available again.
Architecture
User A
(Client)
& Hold System
User B
(Client)
& Release

This diagram shows two users interacting with the reservation and hold system which communicates with the resource database. The system places temporary holds on resources and releases them upon expiry if not confirmed.

Trade-offs
✓ Pros
Prevents double booking by locking resources during the hold period.
Improves user experience by providing immediate feedback on availability.
Allows automatic release of resources if users abandon the booking process.
✗ Cons
Requires careful management of hold expiration to avoid resource starvation.
Adds complexity to the system with timers and state tracking for holds.
Potentially reduces resource availability temporarily due to holds.
Use when resources are limited and contention is high, such as ticket booking or hotel reservations, especially when user decision time is significant (e.g., more than a few seconds).
Avoid when resource availability is abundant or when booking decisions are instantaneous, as the overhead of managing holds outweighs benefits.
Real World Examples
Airbnb
Airbnb uses reservation holds to temporarily lock a property while a user completes payment, preventing others from booking the same property simultaneously.
Ticketmaster
Ticketmaster places holds on seats during the checkout process to prevent double booking and ensure fair access to limited event tickets.
Uber
Uber holds a driver for a rider during the booking process to avoid multiple riders being assigned the same driver.
Code Example
The before code allows direct booking without any temporary lock, risking double booking. The after code introduces a hold system that locks a resource for a user temporarily, preventing others from booking it until the hold expires or is confirmed.
LLD
### Before: No hold system, direct booking
class ReservationSystem:
    def __init__(self):
        self.booked_resources = set()

    def book(self, resource_id):
        if resource_id in self.booked_resources:
            return False  # Already booked
        self.booked_resources.add(resource_id)
        return True


### After: Reservation with hold system
import time
import threading

class ReservationSystem:
    def __init__(self, hold_time_seconds=30):
        self.booked_resources = set()
        self.holds = {}  # resource_id -> (user_id, expiry_time)
        self.hold_time = hold_time_seconds
        self.lock = threading.Lock()

    def place_hold(self, resource_id, user_id):
        with self.lock:
            now = time.time()
            # Clean expired holds
            expired = [r for r, (_, exp) in self.holds.items() if exp <= now]
            for r in expired:
                del self.holds[r]

            if resource_id in self.booked_resources or resource_id in self.holds:
                return False  # Not available
            expiry = now + self.hold_time
            self.holds[resource_id] = (user_id, expiry)
            return True

    def confirm_booking(self, resource_id, user_id):
        with self.lock:
            hold = self.holds.get(resource_id)
            if hold and hold[0] == user_id:
                del self.holds[resource_id]
                self.booked_resources.add(resource_id)
                return True
            return False

    def release_hold(self, resource_id, user_id):
        with self.lock:
            hold = self.holds.get(resource_id)
            if hold and hold[0] == user_id:
                del self.holds[resource_id]
                return True
            return False
OutputSuccess
Alternatives
Optimistic Locking
Instead of holding resources, it allows concurrent access and checks for conflicts at commit time.
Use when: Choose when conflicts are rare and the cost of retries is acceptable.
Pessimistic Locking
Locks resources immediately and exclusively until the transaction completes, blocking others.
Use when: Choose when conflicts are frequent and consistency is critical.
Summary
Reservation and hold systems prevent double booking by temporarily locking resources during user decision time.
They improve user experience by providing immediate feedback and automatic release of unconfirmed holds.
Managing hold expiration and concurrency is critical to avoid resource starvation and ensure fairness.