Guide

Many clients may want the same unit at the same moment. It might be a seat, a coupon, or the last item of a product. The pattern that scales best is a conditional update, a hold that expires, and admission control for the crowd. Locks are the first idea people reach for, and they tend to break under a sudden spike.

Concept

Before you start. A conditional update changes a row only if it still matches a condition, such as status = 'FREE'. A hold is a temporary claim on a unit, with an expiry time. A waiting room lets only a set number of users into the purchase flow at a time.

The big idea

Think of a restaurant that marks a table as "reserved for 10 minutes". The reservation is a hold. If the guest does not arrive, the table goes back on sale. The hold protects the table while it is being decided.

The analogy breaks if the reservation never expires. A table held forever is worse than no reservation at all.

Walking through it

Claim seat 14C with a conditional update. Only one client can succeed.

SQL
UPDATE seats
SET status = 'HELD',
    held_by = 'user-42',
    hold_expires_at = now() + interval '10 minutes'
WHERE id = '14C' AND status = 'FREE';

Output:

UPDATE 1    hold granted for user-42
UPDATE 0    someone else holds 14C; show it as unavailable or try another seat

The flow continues in three steps:

  1. Hold the seat for 10 minutes, as above.
  2. Take payment. Confirm the seat only if the hold is still valid.
  3. A sweeper resets expired holds to FREE, so the seat goes back on sale.

The waiting room sits in front of step 1. It admits a fixed number of users per second, so the database never sees the full spike.

Trade-off

Locks are easy to explain, but they serialize every request on one row, and they die under onsale load. A conditional update, a hold with a time-to-live, and admission control scale much further.

Common mistakes

  • Using SELECT FOR UPDATE on every seat in a flash sale. Requests queue on the locks.
  • Holds with no expiry. A user who closes the tab keeps the seat forever.
  • Confirming without checking the hold. A payment can finish after the hold expired and someone else took the seat.

Check yourself

  1. What does UPDATE 0 tell the client? Another client changed the seat first. The client should show it as unavailable, or pick another seat.
  2. What breaks if holds have no time limit? Abandoned holds keep units locked, so real buyers are turned away.

Key takeaways

  • Use conditional updates on scarce units, not long-held locks.
  • A hold with a time limit protects a unit while a user decides.
  • A waiting room caps how many users contend at once.
  • Confirm a hold before taking payment, and handle an expired hold.

Further learning

The ticket booking case study applies this pattern end to end.

For payment-side safety, see the payment system case study.

Next, see how to keep two systems in agreement after a hold, in multi-step consistency.