Optimistic or pessimistic locking: which should a booking or checkout use?
By Saksham Jain ·
Use pessimistic locking when many users fight over the same row, like the last tickets of one event. Use optimistic locking, a version field, when contention is rare, like bookings or carts spread across many slots and products. Choose by how often two writers realistically hit the same row.
From the production case study Trexind.
| Case | Contention | Choice | Why |
|---|---|---|---|
| Last tickets of one event (FindYourVibe) | High: a burst on one row | Pessimistic row lock | The loser waits milliseconds instead of retrying the whole checkout |
| Appointment and table slots (Trexind) | Low: short writes, rarely contested | Optimistic version field | A lock held across the request isn't worth the latency |
| Stock across many SKUs (Skyxis) | Low: carts rarely hit the same row | Optimistic version field | A lock for the checkout window costs more than the rare retry |
| Submitting an exam attempt (PS Classes) | One-off per attempt | Redis lock on the attempt ID | A submit happens once, so a few milliseconds of lock is cheaper than a corrupted rank |
What is the difference between optimistic and pessimistic locking?
Pessimistic locking blocks other writers while one transaction holds a row, so conflicts wait. Optimistic locking lets everyone proceed, then rejects a write if a version field changed underneath it, so conflicts retry. The first trades latency for certainty; the second trades occasional retries for no waiting.
When is optimistic locking the better choice?
Optimistic locking wins when writes are short and collisions are rare. On Trexind's booking slots a version field means the write that loses a race gets a conflict, not a silent overwrite, and retries against the current slot state. Holding a lock across the whole request would cost more than it saves.
When is pessimistic locking the better choice?
Pessimistic locking wins on a single hot row that many buyers want at the same moment, such as the last few tickets of a popular event. There, optimistic retries thrash and force each loser to redo the whole checkout. A short lock lets the second buyer wait milliseconds and then see sold out.
How do you decide for your own system?
Ask how often two writers hit the same row, and what a lost race costs the user. Rare collisions and cheap retries point to optimistic. Frequent collisions on one row, or retries that redo expensive work, point to pessimistic. Measure contention before committing; the same app can use both.
- Many rows, few collisions per row: optimistic (stock across hundreds of SKUs)
- One row, many simultaneous writers: pessimistic (last tickets of an event)
- Write happens once per entity: a short lock is fine (exam submit)