The Event Ticketing System (like Ticketmaster) is an advanced LLD problem that combines high concurrency handling, waiting lists, dynamic pricing, and complex state management. It's asked for senior SDE roles at companies handling high-traffic sales events.
Core Entities
- Event — name, venue, date, ticket categories
- Venue — sections, seat map
- Ticket — category (GA/VIP/Seated), price, status
- Order — user, tickets, status, payment
- SeatHold — temporary reservation with 5-minute expiry
- WaitingList — FIFO queue per event/category
- PricingEngine — demand-based dynamic pricing
Seat Hold with Concurrency Control
class TicketingService {
holdTickets(eventId: string, category: string, qty: number, userId: string): SeatHold {
// Optimistic locking: version field on TicketInventory
const inventory = this.inventoryRepo.get(eventId, category);
if (inventory.available < qty) throw new Error("Not enough tickets");
const hold = new SeatHold(userId, eventId, category, qty, 5 * 60 * 1000);
// Atomic decrement — DB handles concurrent access
this.inventoryRepo.decrementAvailable(eventId, category, qty, inventory.version);
this.holdRepo.save(hold);
this.scheduleHoldExpiry(hold);
return hold;
}
private scheduleHoldExpiry(hold: SeatHold) {
setTimeout(() => {
if (hold.status === HoldStatus.PENDING) {
this.releaseHold(hold.id);
this.notifyWaitingList(hold.eventId, hold.category, hold.qty);
}
}, hold.expiryMs);
}
}Waiting List with Observer
class WaitingListService {
join(userId: string, eventId: string, category: string, qty: number): WaitingEntry {
const entry = new WaitingEntry(userId, eventId, category, qty);
this.queue.enqueue(eventId + category, entry);
return entry;
}
notify(eventId: string, category: string, availableQty: number) {
while (availableQty > 0) {
const next = this.queue.peek(eventId + category);
if (!next || next.qty > availableQty) break;
this.notificationService.send(next.userId, "Tickets available! You have 10 minutes.");
next.status = WaitingStatus.NOTIFIED;
availableQty -= next.qty;
}
}
}Dynamic Pricing Strategy
class DemandBasedPricing implements PricingStrategy {
getPrice(basePrice: number, soldPct: number): number {
if (soldPct < 0.5) return basePrice;
if (soldPct < 0.75) return basePrice * 1.2;
if (soldPct < 0.9) return basePrice * 1.5;
return basePrice * 2.0; // High demand
}
}