Optimistic locking
Allowing concurrent writes and rejecting the ones that would overwrite a change made since the writer last read.
Rather than locking a record while it is being edited, optimistic locking lets everyone proceed and checks at write time whether the underlying version still matches what the writer read. If it does not, the write is refused and the caller merges. It suits systems where conflicts are rare and holding locks would be worse than occasionally redoing work.
Full guide:
How to resolve a 409 or 412 write conflict without losing data
— Re-read the current version, merge your change into it, and retry with the new version marker. Never refetch and overwrite: that reproduces exactly the bug the conflict check exists to prevent, discarding the other writer's work with no error raised anywhere.
Key facts
- The check happens at write time, so readers are never blocked and a slow editor never holds a lock.
- A rejected write must be merged, not retried unchanged — retrying with a refreshed version silently discards the other writer's change.
- Optimistic locking suits low-contention data; under heavy contention the retry loop can cost more than a pessimistic lock.
- The version marker can be an integer, a timestamp or an ETag, but it must change on every write or the check passes when it should not.
Frequently asked questions
When is pessimistic locking the better choice?
When conflicts are common or a retry is expensive. If two users routinely edit the same row, optimistic locking turns into a livelock of merges and a real lock is simpler.
Why is refetch-and-overwrite wrong after a conflict?
Because it reproduces exactly the bug the check exists to prevent. You read the newer version and then replace it with yours, so the other writer's change is lost without any error being raised.
Machine-readable copy of this page:
/glossary/optimistic-locking.md