How would you handle a scenario where multiple users try to update the same record simultaneously and prevent record locking issues?

Handling Concurrent Updates and Record Locking in Salesforce
When working with Salesforce applications, especially in large organizations with many users, it is common for multiple users or automated processes to update the same record simultaneously. When this occurs, Salesforce enforces strict row-level locking to maintain data integrity. If one transaction is modifying the record, another transaction attempting to update the same record at the same time may fail with the error:
UNABLE_TO_LOCK_ROW
JavaScriptThis is known as a record locking conflict, and it can break business processes if not handled properly.
๐ Why Record Locking Happens
Salesforce uses transaction-based database management. When one transaction reads a record with intent to modify it, Salesforce locks it to ensure:
- No two transactions update the same row at once
- Data values remain consistent
- Preventing duplicate or conflicting updates
Examples of locking scenarios:
- Two users editing the same Account record and clicking Save simultaneously
- Triggers automating updates on the same record from different objects
- Batch jobs running parallel updates
๐ฏ Goal
To handle simultaneous updates without errors or data loss by implementing:
โ Controlled locking
โ Retry logic
โ Preventing unhandled failures
๐ Best Standard Solution: Optimistic Locking + Retry Using FOR UPDATE
In Apex, FOR UPDATE is used to lock the record explicitly during a query. Any other update attempts will wait until the lock is released or retry later based on logic.
๐ Complete Apex Code Example โ Preventing Record Locking
public class SafeRecordUpdateService {
/**
* Prevents record locking issues when multiple users/processes update
* the same record simultaneously by using FOR UPDATE + retry logic.
*/
public static void updateAccountBalance(Id accountId, Decimal amountToAdd) {
Integer maxRetry = 5; // Maximum retry attempts
Integer attempts = 0;
Boolean success = false;
while (!success && attempts < maxRetry) {
attempts++;
try {
// --------------------------------------------------------------
// ๐ธ Query record AND lock it for update using FOR UPDATE
// --------------------------------------------------------------
Account acc = [
SELECT Id, Balance__c, LastModifiedDate
FROM Account
WHERE Id = :accountId
FOR UPDATE
];
// Business logic
acc.Balance__c += amountToAdd;
update acc; // Commit the update
success = true; // If we reach here, update succeeded
} catch (DmlException e) {
// --------------------------------------------------------------
// ๐ธ Catch row lock exception and retry
// --------------------------------------------------------------
if (e.getDmlType(0) == StatusCode.UNABLE_TO_LOCK_ROW) {
System.debug('Record locked. Retrying update, attempt: ' + attempts);
// Wait for other process to finish
System.sleep(200);
} else {
// Rethrow error if not locking related
throw e;
}
}
}
// If failed after maximum attempts, throw meaningful error
if (!success) {
throw new CalloutException(
'Record update failed due to ongoing record lock conflict. Please try again later.'
);
}
}
}
JavaScript๐ก How This Solution Prevents Lock Failure
| Step | Purpose |
|---|---|
FOR UPDATE | Locks record during transaction |
try-catch | Captures lock errors |
| Retry loop | Tries again if record is busy |
System.sleep() | Gives time for lock to release |
With this approach, even in high concurrency situations, updates will wait and retry instead of breaking.
โฑ Alternative Handling Strategy โ UI Conflict Prevention
In UI layers (LWC, Aura, APIs), Salesforce supports optimistic concurrency checking by comparing LastModifiedDate before updating. If a different user modified the record, the system returns a 409 Conflict and the UI can warn the user.
Example API Header:
If-Unmodified-Since: <LastModifiedDate>
JavaScript๐ When Working in Bulk
To minimize locking issues in triggers or batch classes:
โ Group records by Parent ID before updates
โ Ensure child and parent updates are not done in the same transaction
โ Queue long-running updates instead of doing them synchronously
๐ Summary
| Technique | Use Case | Rating |
|---|---|---|
FOR UPDATE | Apex record locking control | โญโญโญโญโญ |
| Retry logic | When record is temporarily busy | โญโญโญโญโญ |
LastModifiedDate matching | UI/API concurrency | โญโญโญโญ |
| Reduce unnecessary DML | Performance optimization | โญโญโญ |
๐ฅ Final Takeaway
Handling simultaneous record updates is not only about avoiding errors but also ensuring data integrity and smooth user experience.
UsingFOR UPDATE + Retry Logicis the most reliable method to eliminate record locking failures in Salesforce.
Related Posts

How to Automatically create a follow-up Task when a Lead is converted

How You need to update a related child record whenever a parent recordโs status changes, but only if the status is โClosed Won.โ How would you design this in Apex?
