Skip to content

Demystifying Optimistic Locking in Databases

Maciej Tomczyk
Maciej Tomczyk | Team Leader 3 min read
Share

Have you ever tried to buy the last concert ticket only to see the message ‘This item has already been sold’? This is a typical concurrency issueIn web applications, it’s common to encounter situations where multiple users try to modify the same data simultaneously. To prevent overwriting changes made by others, a mechanism called optimistic locking is often used.

ORMs like Hibernate or JPA support this out of the box using a version column. But how does it actually work under the hood? Below is a minimal SQL example — no frameworks involved.

How Optimistic Locking Works

Let’s assume there is a table: cats with columns id, name, and version:

CREATE TABLE cats (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    version INT NOT NULL
);


When a user wants to update a record, they first fetch it from the database, including its version value. Later, when the user makes changes and attempts to save them back, the application executes an SQL update with a condition that checks whether the record’s version in the database matches the version the user originally retrieved:

UPDATE cats
SET name = 'New Name',
    version = version + 1
WHERE id = ? AND version = ?;


If the number of updated rows is 0, it means someone else modified the record in the meantime, and the application can notify the user of a conflict.

Practical Example

Suppose there is a cat record with id = 1, name = ‘Whiskers’, and version = 1.

User A fetches the record:

SELECT id, name, version
FROM cats
WHERE id = 1;

-- Result:
(1, 'Whiskers', 1)


User B fetches the same record:

SELECT id, name, version FROM cats WHERE id = 1;

-- Result: (1, 'Whiskers', 1)


User A changes the cat’s name to ‘Fluffy’ and updates the record:

UPDATE cats
SET name = 'Fluffy',
    version = version + 1
WHERE id = 1 AND version = 1;

-- Rows updated: 1


Meanwhile, User B changes the cat’s name to ‘Mittens’ and tries to save it:

UPDATE cats
SET name = 'Mittens',
    version = version + 1
WHERE id = 1 AND version = 1;

-- Rows updated: 0


The key is that the WHERE clause checks the object version.

Receiving a zero number of updated rows signals the application that the data was being modified by another process in the meantime. Since the version no longer matches User B, the update fails, and the user must attempt the update again.

Trade-offs of Optimistic Locking

While offering great benefits for scalability, optimistic locking is not without its trade-offs. The main drawback lies in the required retry logic: when a conflict occurs (i.e., another user has already modified the data), the application must be designed to handle this error, typically by throwing an error and asking the client to retry or re-fetch the latest version of the record, reapplying the user’s changes, and attempting the update again. This necessity for complex error and retry logic adds developmental complexity.

Furthermore, in scenarios with high collision rates, where a record is frequently edited by many concurrent users, the constant cycle of conflicts and retries can degrade the user experience and ultimately slow down the system, mitigating the performance benefits that optimistic locking typically provides.

Yet, for most applications, benefits outweigh drawbacks.

Summary

Optimistic locking is an effective way to manage concurrent access to data in web applications. By maintaining a simple version counter, you can prevent conflicts and ensure data integrity, and it minimizes database locking time, which is crucial for performance and scalability.

Understanding the underlying mechanisms is invaluable, as it helps in diagnosing complex issues and comprehending the precise behavior of the application.

I’ve also shared a small project that demonstrates optimistic locking in action.

You can find it here:

https://github.com/MaciejTomczyk/Demistyfying-Optimistic-Locking

Share
Maciej Tomczyk
Maciej Tomczyk

About

Maciej is a seasoned technology and engineering leader with a strong track record of driving end-to-end software delivery, shaping scalable system architectures, and fostering high-performing development teams. With a hands-on expertise in Java and Kotlin, and deep proficiency in Spring Ecosystem (including Spring Boot), Maciej specializes in building microservices-based, cloud-native applications designed for high availability, fault tolerance, and resilience under heavy load.
@developers
@developers

About

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Contact us about your career

Your next chapter. Become a Jiter

Magdalena Dereszewska

Head of HR