Airline Reservation OOD: Stop Treating “Seat” as a Boolean

bugfree.ai is an advanced AI-powered platform designed to help software engineers master system design and behavioral interviews. Whether you’re preparing for your first interview or aiming to elevate your skills, bugfree.ai provides a robust toolkit tailored to your needs. Key Features:
150+ system design questions: Master challenges across all difficulty levels and problem types, including 30+ object-oriented design and 20+ machine learning design problems. Targeted practice: Sharpen your skills with focused exercises tailored to real-world interview scenarios. In-depth feedback: Get instant, detailed evaluations to refine your approach and level up your solutions. Expert guidance: Dive deep into walkthroughs of all system design solutions like design Twitter, TinyURL, and task schedulers. Learning materials: Access comprehensive guides, cheat sheets, and tutorials to deepen your understanding of system design concepts, from beginner to advanced. AI-powered mock interview: Practice in a realistic interview setting with AI-driven feedback to identify your strengths and areas for improvement.
bugfree.ai goes beyond traditional interview prep tools by combining a vast question library, detailed feedback, and interactive AI simulations. It’s the perfect platform to build confidence, hone your skills, and stand out in today’s competitive job market. Suitable for:
New graduates looking to crack their first system design interview. Experienced engineers seeking advanced practice and fine-tuning of skills. Career changers transitioning into technical roles with a need for structured learning and preparation.
Airline Reservation OOD: Stop Treating “Seat” as a Boolean

In interviews and real-world systems alike, one of the most common design mistakes is modeling Seat.availability as a simple boolean (true/false). A seat is not just "free/busy" — it has distinct states, rules for transitions, and business constraints. Treating it as a boolean hides complexity and invites race conditions, double-bookings, and brittle failure handling.
Below is a concise, practical approach to model seat state and enforce safe transitions.
Model seats as stateful entities
Instead of a boolean flag, model a Seat with an explicit status enum and related metadata:
- Status: Available, Held, Booked (optionally: Blocked, Maintenance, Pending)
- Hold records: who holds it, when the hold expires, hold id / session id
- Booking records: booking id, payment state, timestamps, audit trail
This gives you a cleaner domain model and makes it easy to reason about concurrency and failures.
Typical state machine
- Available -> Held: user starts checkout; create a temporary Hold with an expiry
- Held -> Booked: payment confirms; atomically convert Hold to a Booking
- Held -> Available: hold expires or user cancels
- Booked -> Available: cancellation or refund flow (according to policy)
Enforce transitions through the Booking/Hold APIs rather than letting callers flip a boolean directly.
Implementation notes (practical tips)
- Create an immutable Hold entity with: hold_id, seat_id, user_id/session_id, created_at, expires_at.
- When a user begins checkout, insert a Hold and mark seat as Held (or associate hold with seat). The hold should have a short TTL (e.g., 5–15 minutes).
- Use a single atomic DB transaction when confirming payment to convert the Hold into a Booking. The transaction should:
- Verify the Hold is still valid (not expired and matches hold_id)
- Create the Booking record
- Clear the Hold
- Update seat status to Booked
- If payment fails or the gateway is down, explicitly release the Hold (or let the expiry background job release it). Do not rely on eventual cleanup only.
- Expired holds: run a background job (cron/worker) to remove expired holds and return seats to Available. Emit events if needed.
Concurrency and correctness
- Naive boolean checks lead to race conditions: two processes can read Available simultaneously and both attempt to book.
- Use one of these techniques depending on your scale and DB:
- Optimistic concurrency control (version numbers / CAS) on the seat row and check the Hold id within a transaction.
- Pessimistic locking (SELECT ... FOR UPDATE) for small-scale systems where contention is low.
- Dedicated seat allocation service that serializes operations (actor/queue-based) for very high concurrency.
- Make booking confirmation idempotent: use an idempotency key so retries from the payment system don't create duplicate bookings.
Failure handling and observability
- Make external failures explicit: if payment gateway is down, the flow should fail gracefully and the Hold should either be released or retried within a bounded window.
- Keep audit logs: who held the seat, when, why it was released or booked. This simplifies debugging and chargeback disputes.
- Expose metrics: hold rates, hold expirations, booking success rate, average time from hold->booked.
Why this is better than a boolean
- Prevents double-booking under concurrency
- Makes business rules explicit (hold durations, cancellation rules)
- Simplifies failure handling and retries
- Provides a clearer audit trail and easier testing
Example (pseudocode)
Transaction confirmBooking(holdId, paymentInfo): hold = SELECT * FROM holds WHERE id = holdId FOR UPDATE if not hold or hold.expires_at < now: throw HoldInvalid charge = PaymentGateway.charge(paymentInfo) if not charge.success: throw PaymentFailed INSERT INTO bookings (seat_id, user_id, ...) VALUES (...) DELETE FROM holds WHERE id = holdId UPDATE seats SET status = 'Booked' WHERE id = hold.seat_id COMMIT
This pattern keeps the critical path atomic and makes the edge cases explicit.
Model seats as a small state machine, not a boolean. It reduces bugs, clarifies behavior, and scales much better when concurrency and external failures are in play.



