Optimistic Concurrency Control (OCC) is a strategy used in databases and APIs that assumes conflicts between simultaneous updates are rare. Instead of locking a resource while a user is editing it, the system allows anyone to read and attempt to modify the data. The system only checks for a conflict at the exact moment the user tries to save their changes.
Yes, there is a Pessimistic Concurrency Control (PCC) strategy. It takes the opposite approach, assuming that conflicts are highly likely, and prevents them by locking the resource ahead of time.
Here is a direct comparison of how both strategies operate, using a collaborative document editing example (like Google Docs vs. an older document management system):
Direct Comparison
| Feature | Optimistic Concurrency Control (OCC) | Pessimistic Concurrency Control (PCC) |
|---|---|---|
| Core Assumption | Conflicts are rare. | Conflicts are frequent. |
| Mechanism | Uses versioning / tokens (like ETags or timestamps) at the moment of saving. | Uses locks (Shared or Exclusive) the moment a transaction or edit begins. |
| User Experience | Multiple users can view and edit the same data at the exact same time. | Only one user can edit a resource at a time; others must wait until the lock is released. |
| Failure Scenario | A user finishes editing, hits save, but gets rejected with an error because someone else saved first. | A user tries to start editing but is blocked immediately by a “Resource is locked” message. |
| Best Used For | High-throughput systems, web APIs, and apps with low chances of users editing the exact same record. | Critical data accuracy, long-running batch processes, and systems where conflicts are highly costly. |
How They Work in Practice
1. The Optimistic Flow
- User A and User B both fetch a bank account record at the same time. The current balance is ₹10,000, and the version token (
ETag) is"v1". - User A decides to withdraw ₹2,000.
- User B decides to withdraw ₹5,000.
- User A hits save first. Their request says: “Update balance to ₹8,000 IF the current version is still
v1”. The server checks, matches"v1", applies the change, and bumps the version to"v2". - User B hits save a second later. Their request says: “Update balance to ₹5,000 IF the current version is still
v1”. The server checks, sees the current version is now"v2", rejects the request, and returns an error (like412 Precondition Failed). User B must refresh the data and try again.
2. The Pessimistic Flow
- User A clicks “Edit” on the bank account record. The system immediately places an Exclusive Lock on that row in the database.
- User B clicks “Edit” on the same record a moment later. The system denies them access or forces their application to wait.
- User A takes their time, updates the balance, and hits save. The system saves the data and releases the lock.
- User B is finally granted access to edit the newly updated record.
Why REST APIs Prefer Optimistic Concurrency
REST APIs are inherently stateless. Maintaining a pessimistic lock requires the server to remember who owns the lock across multiple HTTP requests. If a client opens a record to edit it and their internet drops (or they walk away from their computer), a pessimistic lock would leave the database resource frozen indefinitely.
Optimistic locking avoids this entirely by keeping the state tracking on the client side using headers like If-Match.
Would you like to see how to implement optimistic locking in a specific programming language, or are you interested in how databases handle pessimistic locks (like SELECT FOR UPDATE)?