← Architecture Lab

Distributed Seat Locking

Exactly one winner per seat — enforced atomically, verified again at payment, and correct even when holds expire mid-flow.

select seat 14Catomic hold · 2m TTLUser AUser BBooking APIRedisRazorpayMySQL

User A → Booking API → Redis

The hold

User A selects seat 14C for a shuttle-pass window and the seat is held immediately — a single atomic Redis operation (Redis + Lua) with a 2-minute TTL. One hold covers the entire 30–45 day subscription window, so this isn't one ride at stake.

Why not the alternatives?

Database row locks
Holding a DB lock through user think-time and a payment flow pins connections for minutes. Under booking-rush contention that exhausts the pool and takes unrelated queries down with it.
Optimistic locking
Works when conflicts are rare. Seat booking at peak is the opposite — high contention on identical rows — and 'sorry, try again' after entering payment details is hostile UX.
TTL-only expiry (no explicit release)
Tried, effectively — and it produced the self-lockout problem in production. Expiry is the safety net for crashes, not a substitute for releasing holds on every known exit path.
Trusting payment success as booking authority
A completed payment with an expired hold must not produce a booking — otherwise slow payments can double-sell a seat. The hold_token check at confirmation keeps the hold, not the money, as the source of truth; the late payment is cancelled and refunded instead.

Lessons

  • Atomicity is the foundation, but release paths are the feature: every way a user can leave the flow needs a corresponding way for the hold to die.
  • Copying a pattern (BookMyShow-style holds) imports its assumptions; production is where you find out which assumptions weren't yours.
  • Verify the lock again at commit time — a hold that was valid when payment started may not be valid when payment lands, and correctness depends on the second check.
  • Fail fast before money moves, reallocate gracefully after — the layer where you handle a conflict matters as much as handling it.
  • Third-party eventual consistency is your problem, not the provider's — design a grace window rather than surfacing a transient state as a final answer.
Interactive

Now try to break it

You've read how the lock is designed. The simulator gives you two phones and eight seats — take the same seat twice, let a hold expire, pay with a dead token, and watch which defense stops you.

Open the simulator →