Design a Flight Booking System
Design a flight booking system with seat inventory, double-booking prevention, dynamic pricing, and GDS integration.
Quick answer: Design a Flight Booking System
Design a Flight Booking System is covered here as a practical system design interview problem. Design a flight booking system with seat inventory, double-booking prevention, dynamic pricing, and GDS integration. Use it to practice requirements, APIs, storage choices, scaling bottlenecks, data consistency, observability, and failure handling for a medium interview round.
Focus on the problem being solved, the main design choice, the failure mode, and the tradeoff you would defend in front of a senior engineer. This page is part of the DosiBridge system design knowledge graph, so it links related concepts, interview problems, tradeoffs, and references instead of leaving the topic isolated.
Problem Statement
Design a flight booking system like Expedia that lets users search for flights, view seat availability across fare classes, book tickets with seat selection, and handle concurrent booking attempts without double-selling seats. Must integrate with airline Global Distribution Systems (GDS) and support dynamic pricing.
Requirements
Functional
- Search flights by origin, destination, dates, passenger count, and cabin class
- Display available fare classes with prices and remaining seat counts
- Book a flight: temporarily hold seats during payment, confirm or release
- Manage bookings: view itinerary, cancel/modify, check-in
Non-Functional
- Consistency: No double-booking -- seat sold to exactly one customer
- Latency: Search results in <3 seconds (aggregating from multiple airlines/GDS)
- Scale: 500M searches/day, 2M bookings/day, 5K concurrent booking attempts per popular route
- Availability: 99.95% for search, 99.99% for booking confirmation
Core Architecture
-
Flight Search Aggregator -- Fans out search requests to multiple airline GDS connections (Amadeus, Sabre, Travelport) and direct airline APIs in parallel. Merges results, deduplicates, and sorts by price/duration/stops. Caches search results for 15 minutes (prices change but not instantly) to reduce GDS query costs.
-
Seat Inventory Service -- Manages available seats per flight per fare class. Uses PostgreSQL with an optimistic locking pattern:
UPDATE seats SET booked = booked + 1 WHERE flight_id = ? AND fare_class = ? AND booked < capacity. If the UPDATE affects 0 rows, the fare class is sold out. For temporary holds, seats enter a HELD state with a 10-minute TTL, released automatically if payment is not completed. -
Booking Orchestrator -- Saga-based flow: (1) Hold seats in inventory, (2) Collect passenger details and payment, (3) Confirm with airline PNR (Passenger Name Record) creation, (4) Issue e-ticket, (5) Send confirmation. If airline confirmation fails, release hold and refund. Each step is idempotent with the booking reference as the idempotency key.
- Pricing Engine -- Airlines use revenue management (yield management) systems that adjust prices based on: days until departure, current load factor (% seats sold), competitor pricing, and demand forecasts. The booking system receives dynamic pricing from airlines and may add its own markup. Fare rules (refundable, changeable, baggage) vary by fare class.
Database Choice
PostgreSQL for bookings, passenger records, and seat inventory -- ACID transactions prevent double-booking. The seats table uses row-level locks during the hold phase. Redis for search result caching (keyed by route + dates + class, 15-min TTL) and temporary seat hold TTLs. Kafka for booking events consumed by email notification, loyalty points, and analytics services.
Key API Endpoints
GET /api/v1/flights/search?origin=SFO&dest=JFK&date=2024-06-15&passengers=2&class=economy
-> Returns: \{ flights: [\{ flight_id, airline, departure, arrival, duration, fare_classes: [\{ class: "Y", price: 299, seats_left: 12 \}] \}] \}
POST /api/v1/bookings
-> Body: \{ flight_id: "UA-123", fare_class: "Y", passengers: [\{ name, dob, passport \}], payment_method_id: "PM-7" \}
-> Returns: \{ booking_ref: "BK-456", pnr: "XYZ123", status: "CONFIRMED", e_ticket: "..." \}
DELETE /api/v1/bookings/\{booking_ref\}
-> Returns: \{ status: "CANCELLED", refund_amount: 249.00 \}
Scaling Insight
Temporary seat holds with TTL solve the concurrency problem elegantly. When a user selects a flight, seats are held for 10 minutes (not permanently reserved). This prevents the scenario where users abandon checkout with permanently locked seats. A background job releases expired holds every 30 seconds. This means the system can handle 5K concurrent booking attempts: most will get holds, some holds will expire and seats will be re-available, and only completed payments result in permanent bookings.
Key Tradeoffs
| Decision | Option A | Option B | Chosen |
|---|---|---|---|
| Seat inventory | Real-time GDS query per request | Cached + periodic sync | Cached with 15-min refresh -- GDS queries are expensive ($0.01+ each) and slow |
| Double-booking prevention | Distributed lock (Redis) | Database row-level lock | Database lock -- simpler, transactional, no distributed lock coordination needed |
| Hold duration | Short (5 min, more inventory churn) | Long (30 min, less churn) | 10 min -- balances user experience (enough time to enter payment) with inventory availability |
Original DosiBridge notes for Design a Flight Booking System
This section is written specifically for this page, not copied from a general system-design checklist. The useful way to study Design a Flight Booking System is to connect the concept to a scarce or money-moving workflow where duplicate writes and race conditions are more dangerous than slow responses. That framing changes the design discussion from definitions to operating choices.
What makes this topic distinct
- Core Entity: For Design a Flight Booking System, decide the core entity before choosing tools; otherwise the design looks clean but fails when flight changes.
- Read/Write Path: For Design a Flight Booking System, decide the read/write path before choosing tools; otherwise the design looks clean but fails when booking changes.
- Contention Point: For Design a Flight Booking System, decide the contention point before choosing tools; otherwise the design looks clean but fails when flight changes.
- Abuse Path: For Design a Flight Booking System, decide the abuse path before choosing tools; otherwise the design looks clean but fails when booking changes.
- Recovery Workflow: For Design a Flight Booking System, decide the recovery workflow before choosing tools; otherwise the design looks clean but fails when flight changes.
Design a Flight Booking System correctness boundary
For this problem, separate the user-visible action from background work. The correctness boundary is the smallest state transition that must not be duplicated, lost, or reordered. Naming that boundary makes the solution more original than a stock API/database/cache template.
Design a Flight Booking System scaling bottleneck
The first bottleneck should be described in the language of this system: a hot timeline, a contested seat, a busy wallet ledger, a media-processing queue, or a search index update delay. That bottleneck decides which component deserves the deepest interview discussion.
Production review question
If Design a Flight Booking System suddenly receives 10x traffic, which entity becomes contested first, and what queue, lock, shard, or cache protects that entity without hiding correctness bugs?
Practical metric to track
Track flight-booking health as a named dashboard or review item: combine one user-facing metric, one saturation metric, and one correctness metric. For Design a Flight Booking System, this keeps the discussion grounded in behavior that can be measured after deployment instead of generic advice that sounds good in an interview but never gets verified.