System design interview guide
redBus System Design: Seat Booking and Seat Locks
redBus sells more than 100 million bus tickets a year. It works in India, Southeast Asia and Latin America. From April to June 2026, its ticket sales were worth about $502 million. The number of tickets grew 23.9% from a year before (MakeMyTrip filing). But the seats it sells are not its own. They belong to thousands of separate bus operators. And the same seat on the same bus can be sold at the same moment in three places. It can sell on the redBus app, through a travel agent, or at the operator's own counter.
redBus is a marketplace for bus tickets. A traveller searches for buses between two cities on a date. They pick a bus and a seat on a seat map. They pay and get a ticket. It sounds like any booking system. But three things make it hard. First, the seats come from thousands of bus operators. Some run their buses on redBus's own software. Others use their own systems. Second, one seat is one physical thing, but it can be sold in several places at once. Two people must never get seat 14 on the same bus. Third, demand is very uneven. The evening before a festival, everyone wants the same routes at the same time. The main design problem is the seat lock. You hold one seat for one customer while they pay. You release it if they do not pay. And you never sell it twice.
Where it shows up
A natural question for travel and ticketing roles at MakeMyTrip, redBus, Goibibo, IRCTC and AbhiBus. It is also one of the most common interview questions in its general form. Design a bus, train, flight, cinema or event booking system.
Why this question is asked
Seat booking is the clearest test of whether a candidate understands many things happening at once. Anyone can draw search, a booking service and a payment service. One question decides the interview. Two people tap the same seat at the same second. What happens? Then come the harder follow-ups. How long do you hold a seat? What if payment arrives after the hold ends? And how do you keep one seat correct when other systems, like an operator's counter, can also sell it?
Requirements
Always clarify these in the first 5 minutes of the interview. Do not start drawing boxes until both lists are agreed.
Functional requirements
- Search buses between two cities on a date, with times, prices, bus type and ratings
- Show a seat map for one trip, with each seat's price and whether it is free
- Hold the chosen seats for the customer while they enter details and pay
- Confirm the booking and give a ticket when payment works
- Release held seats if the customer does not pay in time
- Handle cancellations and refunds under each operator's rules
- Operators manage their buses, routes, prices and seat layouts
- Partner agents can sell the same seats, not only the redBus app
Non-functional requirements
- Never sell the same seat on the same trip to two people
- Search is fast, even though results come from thousands of operators
- The seat map is close to live, so people rarely pick a seat that is gone
- Handle festival and long-weekend peaks, when demand jumps many times over
- A slow operator system must not slow down search or booking for others
- Every booking and payment can be matched, so nobody pays without a seat
Back-of-envelope scale estimates
Show your math. Pulling numbers from thin air signals you have not thought about the load.
Tickets per year
100 million+
A March 2026 case study puts redBus at more than 100 million bookings a year. It was published by CubeAPM, a monitoring company that redBus uses. A company's case study is not an audited number. So treat it as the right size, not an exact count.
Average bookings
~3 per second, all day
100 million tickets a year, divided by 31.5 million seconds in a year, is about 3 a second. This is my estimate. Bookings bunch up in the evening and before festivals. Searches happen many times more often than bookings. So plan for thousands of searches a second at the peak.
Ticket sales per quarter
~$502 million
MakeMyTrip reported bus ticket sales of $501.9 million for April to June 2026, in its SEC filing. That was up 20.8%, or 31.4% at fixed exchange rates. This is the value of tickets sold, not redBus's revenue.
Ticket growth
+23.9% a year
MakeMyTrip's filing says the growth came from 23.9% more bus tickets than a year earlier. So plan for peaks that grow at least this fast.
Seats per trip
~30 to 50
A typical sleeper or seater bus has about 30 to 50 seats. This is my estimate. It is what makes the problem hard. The lock is on a tiny, fixed set of seats. So a popular trip gets heavy competition, even though total volume looks small.
Markets
India, Southeast Asia, Latin America
MakeMyTrip's filing says redBus works in some countries in Southeast Asia and Latin America, as well as India. Each market adds its own money, payment methods and time zones. But the seat lock problem is the same everywhere.
High-level architecture
Split the design into two paths with very different needs. The search path is mostly reads. It can be a little out of date. It answers which buses run between two cities on a date, with times and starting prices. Build it from a search index that is refreshed from operator data. Cache it heavily. A million people looking at Bangalore to Chennai on a Friday mostly see the same results. The booking path is mostly writes, on a tiny set of seats. It must be exactly right: this seat, on this trip, for this customer. Its heart is a seat service. It owns the state of every seat on every trip. It is the only thing allowed to change it. A seat has three states: free, held for one customer until a time, and booked. Holding a seat is one update. It works only if the seat is free. So two customers can never both hold it. Payment happens while the hold is active. If payment works, the seat becomes booked and a ticket is made. If the hold runs out first, the seat is free again. Seats reach redBus in two ways. Some operators run their buses on redBus's own cloud software, called BOGDS. Their seats live in redBus's systems. Other operators use their own software. redBus reaches them through a connection layer. A hold must be placed in the operator's system too, because their counter can sell the same seat. Most real-world failures happen in that connection.
In a real interview, sketch this on the whiteboard before diving into any single box.
Core components
Walk through each service. The interviewer wants to hear what each one owns, not just the names.
Search and listing
It answers 'which buses run from A to B on this date'. It uses a search index of trips, prices and ratings, refreshed from operator data. It is cached by route and date. It can be a little out of date. The seat map and the hold are where seats are really checked.
Seat service
It owns the state of every seat on every trip: free, held or booked. It is the only writer. Data is split by trip. So a rush on one popular bus never touches the data of any other bus.
Seat hold (the lock)
It holds the chosen seats for one customer for a few minutes while they pay. A hold is an update with an end time. It is not a database lock kept open. So a customer who closes the app cannot block a seat forever.
Operator connection
It connects to operators who run their own booking software. It places and releases holds in their systems. It fetches their seat maps and confirms bookings. Each operator has its own time limit and a circuit breaker. So one slow operator cannot stall booking for everyone.
Booking and payment
It creates the booking and takes payment while the hold is active. It confirms the seat when payment works. A booking ID is made first and used everywhere. So a repeated payment message never books twice or charges twice.
Selling through partners
Other agents sell the same seats. Wikipedia says redBus runs SeatSeller, a system that shares bus seats with agents. Every partner sale goes through the same seat service and the same hold rules. That is the only way one seat stays correct everywhere.
Cancellations, refunds and matching
It applies each operator's cancellation rules, refunds the customer and puts the seat back on sale. A daily check compares bookings, payments and operator records. It catches the rare case where someone paid but got no confirmed seat.
Data model
Pick the right store per table. Justify each choice with the access pattern, not by reflex.
tripstrip_id (PK)operator_idroute_iddeparture_atbus_layout_idsource (bogds/external)One scheduled run of one bus. The source column says where the truth for its seats lives. It is either redBus's own operator cloud, or the operator's own system.
seatstrip_idseat_nostate (available/held/booked)hold_idhold_expires_atbooking_idversionThe heart of the design, split by trip_id. Only the seat service writes here. Every change depends on the current state. That is what makes selling one seat twice impossible.
holdshold_id (PK)trip_idseat_noscustomer_idexpires_atstateOne customer's short claim on one or more seats. The end time is checked in the seats table. A background job also clears old holds. So a missed clean-up can never keep a seat off sale.
bookingsbooking_id (PK)hold_idtrip_idseat_noscustomer_idamount_minorpayment_idstateoperator_refThe confirmed ticket. The booking_id is made before payment starts. It stops repeated payments and repeated operator confirmations. Amounts are whole numbers in the smallest unit of money.
farestrip_idseat_classfare_minorvalid_fromOperators change prices often, especially close to departure. The price is read when the hold is placed and saved on the booking. So the customer pays the price they saw.
Deep dives
These are the conversations the interviewer is steering you toward. Practice each one until you can talk through it without notes.
Two people tap seat 14 at the same second
This is the whole interview. Say the booking service reads 'seat 14 is free', then writes 'seat 14 is held'. Two customers can both read 'free' before either one writes. Then both think they have the seat. The fix is to make the check and the change one step. Hold the seat only if it is still free, in one update. The database runs one customer's update first. The second update finds the seat already held and changes nothing. So the app can say at once: 'this seat was just taken, pick another'. Seats are split by trip. So this contest only involves the 30 to 50 seats of one bus. It stays fast even when that bus is the most wanted trip of the weekend. We tested this exact statement on PostgreSQL with two sessions racing for one seat. Only the first one got it.
UPDATE seats
SET state = 'held', hold_id = $3,
hold_expires_at = now() + interval '8 minutes'
WHERE trip_id = $1 AND seat_no = $2
AND (state = 'available'
OR (state = 'held' AND hold_expires_at < now()));
-- 0 rows updated: someone else has the seat
How long to hold a seat
A hold that is too short fails honest customers who pay slowly. A bank OTP in the middle can take a while. A hold that is too long keeps seats away from people who want them. On a sold-out festival bus, other customers see 'no seats' while seats sit unpaid. A common answer is a few minutes. That is long enough for a normal payment. Show the countdown to the customer. The end time must not depend on a clean-up job running on time. That is why the update above treats an old hold as free. The clean-up job is only there to tidy up.
Payment works after the hold has ended
This is the awkward case. The customer paid. But the bank's confirmation came after the hold ran out. The seat is now held by someone else. The system must never give one seat to two people. So the late payment cannot just book it. The booking service tries to confirm. The update fails, because the hold no longer matches. The booking moves to 'payment received, seat lost'. The customer gets an automatic refund. Ideally, they are offered another seat on the same bus right away. The point is that this case is planned for. It never leaves a customer charged with no ticket.
One seat, many sellers
One seat can be sold in three places. It can sell on the redBus app, through agents, or at the operator's counter. If each place kept its own copy of the seat map, the same seat would be sold twice. For operators on redBus's own software, the fix is simple. Every seller goes through the same seat service and the same hold. For operators on their own software, the truth lives in their system. So a hold on redBus must also be placed there before the customer pays. The booking must also be confirmed there before the ticket is made. That call can be slow, or it can fail. So the operator's answer is the final word, not redBus's copy.
Keeping one slow operator from slowing everyone
With thousands of operators, some connections will always be slow or down. If the booking path waits on them with no limit, one broken operator ties up the service. Then every customer's booking slows down. So each operator connection gets its own time limit. It gets its own small set of connections. And it gets a circuit breaker. The breaker stops calling an operator that keeps failing, and shows its buses as unavailable for a while. The same case study notes that one broken service can cause slow search, seat lock failures or payment timeouts. This separation exists for exactly that.
The festival rush
Before Diwali, Pongal, Onam or a long weekend, demand for a few routes jumps many times over. It happens in the same evening hours. Search handles this with caching by route and date, since most people see the same results. The seat map and holds cannot be cached. But they are split by trip. So the load spreads across every bus on those routes. It does not land on one shared table. The operator connections and the payment gateway need the most planning. They see the full booking peak at once. Rate limits and queues in front of them stop a burst from becoming a failure.

Trade-offs to discuss
Every senior interviewer expects you to surface at least 3 of these. Pick the decisions, state the alternatives, and justify your choice.
Short holds versus long holds
Short holds keep seats on sale and are fair to others on a busy bus. But they fail slow payers. Long holds are kind to the payer, but they hide seats from everyone else. A few minutes, with a visible countdown, is the usual balance. The rare late payment gets an automatic refund.
One database update versus a separate lock service
A separate lock service, like locks in Redis, is fast. But after a crash or a network problem, the lock and the seat record can disagree. Doing the hold as one update on the seat row keeps the lock and the data together. They cannot drift apart. It is slightly slower per request, but much simpler to get right.
Cached search versus live seat counts in search
Live seat counts for every bus in every search would mean asking thousands of operators each time. That is slow and fragile. Cached results with a refresh time are fast and cheap. Sometimes they list a bus whose last seats just sold. The seat map, loaded when the customer picks a bus, shows seats correctly.
Hosting operator seats versus connecting to operators' own systems
When operators run their buses on redBus's cloud, redBus holds the truth. Every seller stays in sync. When operators keep their own software, redBus must call it for every hold and booking. That is slower and can fail. So offering operators the hosted software is about reliability as much as business.
Confirm with the operator before the ticket versus after
Giving the ticket first and confirming later is faster. But if the operator says no, the customer holds a ticket for a seat that does not exist. Confirming first is slower and depends on the operator's system. But the ticket is only given when the seat is really theirs.
How redBus actually does it
The growth numbers come from MakeMyTrip's own SEC filing for April to June 2026. The 100 million tickets a year comes from a March 2026 case study. It was written by CubeAPM, a monitoring company that works with redBus. The names BOGDS (the operator cloud) and SeatSeller (the seat-sharing system) come from Wikipedia. The company has not published how its booking systems are built. So this is a standard seat-booking design that fits those facts. It is not a description of redBus's code. Estimates like seats per bus and peak load are mine, and they are marked.
Lessons to study before this interview
If any of these topics are fuzzy, the interviewer will catch it. Each lesson is 15 to 60 minutes with diagrams, code, and a quiz.
Distributed Locks
advanced / distributed systems core
Idempotency Keys
intermediate / api design protocols
Circuit Breaker
advanced / reliability resilience
Timeout Patterns
advanced / reliability resilience
Cache-Aside Pattern
foundation / caching strategies
Search Engines
intermediate / database types storage
Saga Pattern
advanced / distributed systems core
Related system design interview questions
Practice these next. They lean on the same core building blocks as redBus.