# Optimistic locking vs Pessimistic locking

> Optimistic locking detects conflicting changes before accepting a write; pessimistic locking acquires locks before making changes that depend on protected state. Choose optimistic locking when conflicts are uncommon or work spans user interaction, and pessimistic locking for short transactions where competing writers would otherwise repeatedly invalidate each other's work.

Source: https://sysround.com/compare/optimistic-locking-vs-pessimistic-locking
Updated: 2026-11-05


## Side by side

| | Optimistic locking | Pessimistic locking |
|---|---|---|
| Basic approach | Read, compute, then validate before writing | Lock protected state, then read and update |
| Typical implementation | Version column with a conditional UPDATE | SELECT ... FOR UPDATE inside a transaction |
| Conflict behavior | Reject a stale write; retry or report conflict | Wait, fail immediately, or time out |
| Low contention | Avoids holding locks during application work | Adds lock acquisition and holding time |
| High contention | Repeated conflicts can waste work | Serializes access, but can create long queues |
| Long workflows | Validate versions after user or network delays | Unsuitable for holding database locks across delays |
| Failure handling | Bound retries and preserve user intent | Handle deadlocks, timeouts, and transaction aborts |
| Protection scope | Must validate every relevant dependency | Must lock every relevant row or predicate |

## The differences that matter

Optimistic locking makes the write conditional on the state you previously read. For example, UPDATE documents SET body = ?, version = version + 1 WHERE id = ? AND version = ? succeeds only if the version still matches. Check the affected-row count: zero means the expected version was not updated. Every writer must follow the versioning rule, or stale updates can slip through.

Pessimistic locking protects a read-modify-write sequence inside a transaction. A typical SQL flow is BEGIN, SELECT ... FOR UPDATE, validate the current state, UPDATE, then COMMIT. Competing writers to the protected rows generally wait or fail according to the database and configuration. Ordinary readers may still read an older committed version under MVCC.

The main performance question is contention on the same protected state, not total requests per second. Optimistic locking works well when writers mostly touch different records. With a hot record, failed validations and retries can amplify load. Pessimistic locking can avoid repeated application work, but lock queues still limit throughput and can exhaust connection pools.

Neither approach automatically protects an invariant involving multiple records. Checking versions only on rows you update can miss write skew when a decision depends on other rows. Likewise, locking existing rows may not prevent a new matching row from being inserted. Identify the full invariant, then use appropriate constraints, a shared guard row, predicate protection, or serializable transactions.

Application-level optimistic locking is not the same as a database never taking locks. A conditional UPDATE may acquire a write lock internally. Conversely, a database row lock is not a durable business reservation: for checkout or payment workflows, commit a hold with an expiration time rather than keeping a transaction open across user interaction or external calls.

## Choose Optimistic locking when

- Conflicting writes to the same record are uncommon, so version checks usually succeed on the first attempt.
- A user edits a document or configuration over seconds or minutes, and stale saves should produce a conflict instead of silently overwriting newer work.
- Computation can happen outside a transaction, and restarting it after a conflict is inexpensive and safe.
- Clients submit updates through an API using a version or ETag, allowing the server to reject stale changes without holding a database connection.

## Choose Pessimistic locking when

- A short read-modify-write transaction frequently competes with other transactions for the same rows.
- Several related rows must be inspected and updated together, and you can define a consistent lock acquisition order.
- Recomputing a transaction after repeated optimistic conflicts is costly, while the protected work can remain short.
- You need to claim a database-backed work item, and row locks with SKIP LOCKED fit the queue's ordering and fairness requirements.

## Worked example: A seat hold is not a database lock

Suppose 500 buyers attempt to hold the same concert seat. With optimistic locking, each request can conditionally change the seat from AVAILABLE at version 12 to HELD at version 13. One succeeds; the others must treat the failed condition as unavailable inventory, not retry forever. With pessimistic locking, each request locks the seat row, checks its state, and either creates the hold or rejects the request. Waiting requests can still overload the database, so admission control matters with either approach. Commit the hold immediately with a five-minute expiration. Do not keep the database lock while the buyer enters payment details; confirm or expire the durable hold through later conditional transitions.

## In the interview

- State the invariant first: one confirmed owner per seat, no negative available balance, or no silent overwrite of a document revision. Then identify exactly which rows and decisions need protection.
- Show the transaction or conditional write, not just the technique's name. Explain the version predicate and affected-row check, or the lock acquisition and commit boundary.
- Discuss contention per key and transaction duration. Expect follow-up questions about hot inventory, retry amplification, lock wait latency, connection-pool exhaustion, and admission control.
- Define failure behavior. For optimistic conflicts, use bounded retries only when recomputation preserves intent. For pessimistic locking, set transaction deadlines, use consistent lock ordering, and handle deadlock aborts.
- Separate database concurrency from workflow correctness. Interviewers may ask what happens after a payment timeout, process crash, or duplicate request; use durable state transitions, idempotency, and reconciliation rather than a long-held lock.

## Common mistakes

- Calling optimistic locking lock-free, or assuming pessimistic locking blocks every reader. Actual behavior depends on the database, isolation level, and statement.
- Choosing solely from overall traffic volume. A high-throughput service with independent keys can have little contention, while a small service can have one heavily contested row.
- Automatically retrying every conflict. A stale document edit may require a merge or user decision, and retrying an external side effect can duplicate it.
- Assuming either technique guarantees serializability or protects an entire business invariant without checking all dependent rows, inserts, and write paths.

## Interview questions where it comes up

- [Design a ticket booking system like Ticketmaster](https://sysround.com/questions/design-ticketmaster): Seat allocation requires atomic ownership transitions under contention, followed by durable holds rather than locks held through payment.
- [Design a hotel booking system](https://sysround.com/questions/design-hotel-booking-system): A multi-night reservation must protect inventory across all requested dates without allowing partial allocation or overselling.
- [Design a payment system](https://sysround.com/questions/design-payment-system): Concurrent refunds and payouts require transaction boundaries that preserve balance invariants independently of external payment calls.
- [Design Wikipedia or Notion](https://sysround.com/questions/design-wikipedia): Version-checked saves prevent silent overwrites and provide a clear point for conflict reporting or merging.
- [Design a ride hailing app like Uber](https://sysround.com/questions/design-uber): Competing matchers need an atomic transition that prevents a driver from being assigned to multiple active trips.
- [Design a distributed message queue like RabbitMQ](https://sysround.com/questions/design-message-queue): Database-backed worker claims can use row locking or conditional state transitions, while durable leases handle processing after the claim commits.

## FAQ

### What is the difference between optimistic and pessimistic locking?

Optimistic locking allows work to proceed and validates that relevant state has not changed before accepting the update. Pessimistic locking acquires locks before proceeding with work that depends on protected state. The trade-off is conflict rejection and possible recomputation versus lock waiting and longer resource occupancy.

### Which is better for high contention: optimistic or pessimistic locking?

Pessimistic locking can be better for short, highly contested transactions because competing requests wait rather than repeatedly recompute. It is not a throughput guarantee: all requests still compete for the same protected resource, and queues can grow. Atomic conditional updates, shorter transactions, and admission control may matter more than switching locking styles.

### Does optimistic locking prevent double booking?

Yes, when an atomic conditional write or transaction protects the actual booking invariant and every writer follows that rule. A version check on one seat row can prevent two requests from acquiring that seat, but a date-range booking may require coordinated checks across multiple inventory rows. A plain read followed by an unconditional write is not sufficient.

## Related concepts

- [Optimistic locking](https://sysround.com/concepts/optimistic-locking)
- [Transaction isolation levels](https://sysround.com/concepts/isolation-levels)
- [MVCC](https://sysround.com/concepts/mvcc)
- [Serializability](https://sysround.com/concepts/serializability)
- [Two-phase locking](https://sysround.com/concepts/two-phase-locking)


---
SysRound (https://sysround.com) is an AI practice tool for system design interviews: a voice or typed AI interviewer, a shared whiteboard, then feedback on every skill and a model answer. Its feedback is AI-generated and can be wrong.
