Short answer (interview-ready)
Under high contention, optimistic locking degrades by producing frequent conflicts, causing retries, increased latency, and potential livelock or starvation.
It stops scaling not by blocking, but by wasting work.
That sentence alone already sounds senior.
Now let’s unpack it properly.
What “high contention” means here
High contention =
Many concurrent transactions update the same rows.
Example:
- Same account
- Same inventory item
- Same counter
- Hot partition / hot key
What happens under high contention (step by step)
Example with version-based locking
- 10 transactions read:
balance = 1000, version = 42
All calculate:
newBalance = 900
First transaction updates:
UPDATE account
SET balance = 900, version = 43
WHERE id = 1 AND version = 42;
✔ success
- Remaining 9 transactions execute:
... WHERE version = 42;
❌ 0 rows updated → conflict
- They must:
- reload
- recompute
- retry
🔁 Loop repeats.
Failure modes of optimistic locking under contention
1️⃣ Retry storm (most common)
- Many transactions fail
- All retry almost simultaneously
- CPU spikes
- DB load increases
- Throughput collapses
📉 More retries ≠ more progress
2️⃣ Livelock
System is:
- Busy
- Consuming CPU
- Doing work
But:
- Very little actual progress
- Transactions constantly invalidate each other
💥 System looks alive but makes no progress.
3️⃣ Starvation
- Some transactions never succeed
- Faster or luckier clients win repeatedly
- Others keep failing version checks
Especially dangerous in:
- Distributed retries
- Client-side retry loops
4️⃣ Latency explosion
- Each logical operation becomes:
read → compute → fail → retry → read → compute → fail ...
Tail latency grows massively
SLAs break
5️⃣ Hot-row amplification
- Every retry re-reads the same hot row
- Cache churn
- Lock manager pressure (yes, even without explicit locks)
Why optimistic locking still “works” (important nuance)
Optimistic locking:
- Preserves correctness
- Never corrupts data
- Never deadlocks
But:
- It fails by inefficiency, not by inconsistency
This is why it’s dangerous in financial or inventory systems.
Contrast with pessimistic locking under contention
| Aspect | Optimistic | Pessimistic |
|---|---|---|
| Behavior | Many retries | Blocking |
| CPU usage | High | Lower |
| DB load | High | Predictable |
| Latency | Unstable | Stable |
| Throughput | Degrades sharply | Degrades smoothly |
🔑 Pessimistic locking degrades gracefully.
How experienced systems handle this (very senior)
1️⃣ Switch strategy dynamically
- Optimistic for normal load
- Pessimistic for hot paths
2️⃣ Backoff & jitter on retries
retry → sleep(random 10–50ms) → retry
Reduces retry storms.
3️⃣ Partition the hot key
- Sharded counters
- Bucketed balances
- Append-only ledger + async aggregation
4️⃣ Combine with idempotency keys
- Prevent duplicate logical operations
- Reduce retries at business level
Typical interview mistakes ❌
- “Optimistic locking is faster” → ❌ (only under low contention)
- “Just retry until success” → ❌ (livelock)
- “Database will handle it” → ❌
- “Use bigger DB” → ❌
Interview-ready final answer (say this)
Under high contention, optimistic locking causes frequent version conflicts, leading to retries, increased latency, and wasted work.
While correctness is preserved, the system can experience retry storms, livelock, and starvation, causing throughput to collapse.
In such cases, pessimistic locking or redesigning the data model is usually more appropriate.