Seat reservation and ticketing

Routes, departures, seat maps and the tickets sold against them — for bus, rail or anything else where a specific seat on a specific journey is the thing being sold.

Talk about scope

Everything turns on holding a seat correctly

A reservation system is a concurrency problem wearing a booking form. The interesting moments are all contention: two people reaching for the last seat at once, a payment that confirms after its hold expired, an operator swapping in a smaller vehicle after tickets are sold. Systems that model a booking as a row inserted at checkout work perfectly in testing and fail on the departures that matter, because those are precisely the ones where more than one person is trying at the same time.

One seat · its statesThe forward path is the demo. The two returns are the system: a hold that lapses must release the seat, and a payment that confirms after it lapsed needs a defined answer rather than an exception in a log.
FREEsellable
HELDexpires in 10:00
PAIDgateway confirmed
TICKETEDon the manifest
  • HELD → FREEthe hold expired and nobody paid
  • PAID → FREEpayment landed after expiry — refund, or honour it and find another seat
  • TICKETED → FREEcancelled inside the refund window, seat returns to sale

What we would build

A seat is held before it is paid for

Between choosing a seat and completing payment, that seat cannot be sold to anyone else — and it cannot be held forever either. The hold, its expiry, and what happens when payment succeeds after the hold lapsed are the core of the system, and getting them wrong is how two people arrive with a claim to the same seat.

Inventory that is created by a schedule

Seats do not exist as stock; they are generated by a route running on a date. Change the vehicle and the seat map changes under bookings that already exist. The schedule, the vehicle and the seat map are separate things bound together per departure, not one table.

The last few seats are contested

Demand concentrates on popular departures, which means simultaneous attempts on the same seat are normal rather than rare. This needs real locking at the seat level, and a checkout that fails clearly and immediately rather than optimistically accepting and apologising afterwards.

Payment failure is the common path

Cards decline, gateways time out, and users abandon at checkout constantly. Every one of those has to release the held seat promptly and leave no partial booking behind — and a payment that confirms late, after the hold expired, needs a defined answer rather than an exception in a log.

Cancellation and change are the business

Refund windows, partial refunds, date changes and no-shows are where the operator makes or loses money, and where customers complain. These rules change often and per operator, so they belong in configuration with an audit trail, not compiled into the booking flow.

The manifest has to be right at departure

Whoever is at the vehicle needs the current passenger list, including the booking made twenty minutes ago and the cancellation made ten minutes ago, on whatever connection exists at a bus stand. Offline-tolerant and reconciling is the requirement; a web page that needs signal is not.

When not to build this

A packaged product is the right answer more often than a development company usually admits, and if your problem is an ordinary one that something off the shelf already solves, we will tell you so rather than quote for it. What follows is the case for the other answer — the conditions under which building is worth what it costs.

The workaround has become the process

A packaged system that mostly fits leaves a residue — the spreadsheet kept alongside it, the step done by hand every month, the field used to mean something it was not named for. When that residue is where the actual work happens, you are already maintaining custom software, just without any of the benefits of having built it.

The thing you do differently is the thing it cannot do

Every business has a few processes that are genuinely its own, and those are usually the ones it competes on. Off-the-shelf software is built for the average of a sector, so it handles the ordinary parts well and the distinctive part not at all. Building is worth it exactly where that overlap fails, and rarely anywhere else.

A vulnerability shared by every deployment

A vulnerability in a packaged product is a vulnerability in every deployment of it, and attackers only have to find it once. A system built for one business is not on that list.