Optimistic vs Pessimistic Locking

Intermediate
8 min read· Backend & Databases

When two transactions update the same row at once, one update can silently overwrite the other — the lost-update problem. Locking prevents it. Pessimistic locking assumes conflict is likely and locks the row up front so others must wait. Optimistic locking assumes conflict is rare, lets everyone proceed, and detects a clash at write time using a version column — failing the loser so it can retry. Choosing between them is about how much contention you expect.

Think of editing a shared document

Pessimistic locking is checking out the document so only you can edit it — nobody else touches it until you check it back in. Safe, but others sit idle waiting. Optimistic locking is everyone editing freely; when you save, the system checks whether the document changed since you opened it. If it did, your save is rejected and you reload and try again. Great when clashes are rare, wasteful if everyone edits the same paragraph.

Step by Step

1 / 5

Key Concepts

Lost Update

When two concurrent transactions read then write the same row, and one overwrites the other change. Both locking strategies exist to prevent this.

Version Column

An integer or timestamp on the row that increments on every update. Optimistic locking compares the version at write time to detect concurrent modification (JPA @Version automates this).

SELECT FOR UPDATE

The SQL statement that acquires a pessimistic row lock, forcing other transactions to wait until the lock holder commits or rolls back.

Deadlock

Two transactions each hold a lock the other needs and wait forever. More likely with pessimistic locking; avoided by acquiring locks in a consistent order and keeping transactions short.

Key Facts

  • Optimistic locking adds no database locks and scales beautifully when conflicts are rare — but the application must handle the retry when a write is rejected.
  • Pessimistic locking guarantees the writer succeeds without retries, but holding locks reduces concurrency and risks deadlocks.
  • ORMs make optimistic locking easy: a @Version field in JPA/Hibernate triggers the version check automatically and throws on conflict.

Real-World Applications

Editing a user profile

Profile edits rarely collide, so optimistic locking with a version column is ideal — no locks in the common case, and a rare "someone else just updated this, please reload" message on conflict.

Decrementing hot inventory

For the last few units of a flash-sale item, contention is intense; pessimistic locking (SELECT FOR UPDATE) serialises the decrement so two buyers cannot both claim the last unit.

Frequently Asked Questions

What is the difference between optimistic and pessimistic locking?

Pessimistic locking locks a row before working on it, so others wait — preventing conflict by serialising access. Optimistic locking lets everyone proceed and detects conflicts at write time using a version check, rejecting and retrying the loser. Pessimistic suits high contention; optimistic suits low contention and read-heavy systems.

How does optimistic locking detect a conflict?

The row has a version column. A transaction reads the current version, and its update includes a condition like WHERE version = <read value>, also incrementing the version. If another transaction already changed the row, the version no longer matches, zero rows are updated, and the write is rejected so the application can retry.

When should I use pessimistic locking?

When conflicts are frequent and retries would be expensive or unfair — for example, decrementing scarce inventory or transferring funds on a hot account. Locking the row up front guarantees the operation succeeds once without repeated optimistic failures.

Does optimistic locking cause deadlocks?

No — because it holds no database locks, optimistic locking cannot deadlock. Its cost is retries on conflict. Deadlocks are a risk of pessimistic locking, mitigated by acquiring locks in a consistent order and keeping transactions short.

Related Topics