29 August 2026   6 min read

The seat hold is the whole booking system

Three booking platforms in, the same problem shows up every time: reserving a finite resource when two people press the button at once.

Every booking system I have built looks different on the surface and is identical underneath. A bus seat, a hotel room and a restaurant table are the same object: a finite resource, claimed over an interval, by one party at a time.

The naive implementation checks availability and then writes the booking. Between those two statements is a window, and in that window somebody else can pass the same check. In development you will never see it. In production it happens the first busy evening.

The fix is not clever. Do the check and the claim inside one transaction, and lock the row you are checking. In Django that is select_for_update on the queryset. The second request waits, then re-reads, then correctly fails.

The second problem is the abandoned checkout. A seat held for a payment that never completes is a seat nobody can buy. Give every hold an expiry and clear expired ones on a schedule. A booking system without hold expiry slowly sells out of nothing.

All notes