Lesson 13 of 19
17. Transactions and Locking

17.12 How do seat holds with expiry work?

3 min read+10 XP

On the train: "Seat 14 is held for you for 10 minutes. Pay by 10:12 or it goes back on sale." Nobody else can take it meanwhile, and nobody can hog it forever.

In the system: A hold (reservation) splits booking into two steps, so a user isn't racing others while typing card details:

free ──hold(user, expires = now + 10 min)──▶ held ──pay in time──▶ sold ▲ │ └────────── hold expires or user cancels ────┘
  1. Hold: atomically move the seat from free to held with the user and an expiry time (an atomic conditional update or a unique constraint makes sure only one hold wins).
  2. Pay: the payment step checks the hold is still yours and not expired, then marks it sold.
  3. Expire: a background job (or a check on every read) returns expired holds to free.

In the chapter's code, Ravi can't take seat 1 while Asha holds it; once her 10 minutes pass, Ravi gets it and Asha's late payment is refused.

Details that matter:

  • Choose the hold time from how long payment really takes; too long and seats sit idle while real buyers are turned away.
  • Use the database's clock, or one trusted clock, for expiry, not each app server's.
  • Payment arriving just after expiry: decide the rule (refund automatically) and make it idempotent.
  • Limit holds per user so bots can't hold every seat (Chapter 25).

Memory code: "Hold it, pay for it, or lose it."