Try Serpent Free

How to fix UNABLE_TO_LOCK_ROW in Salesforce deployments

A record the deployment needs to update is locked by another transaction running at the same time.

Surfaces during: runtime DML, a timing collision rather than a metadata or data problem

What it means

UNABLE_TO_LOCK_ROW means Salesforce could not acquire a lock on a record because another transaction, a batch job, a scheduled flow, or a concurrent Apex test, was already updating it. This is a timing problem, not a metadata problem: the deployment or its tests are correct, but they collided with something else running in the org.

It's especially common with master-detail relationships, since updating any child record acquires a lock on the parent for roll-up summary recalculation, so two child inserts racing to update the same parent at once will contend for that lock.

Diagnosis

Common causes

Deploying during active org usage
Another user or scheduled process is updating the same parent records while the deployment's Apex tests run.
Tests updating a shared singleton record
Multiple test classes update the same org-wide configuration or settings record in parallel.
Master-detail rollups contending for the parent
Several child inserts trigger roll-up summary recalculations on the same master record at once.

The fix

  1. Retry the deployment
    Row locks are transient. Re-running the same deployment often succeeds once the competing transaction finishes.
  2. Deploy during a low-activity window
    Schedule production deployments outside business hours or pause conflicting scheduled jobs first.
  3. Avoid shared record contention in tests
    Restructure Apex tests so they do not all update the same singleton settings record within the same transaction.
    for (Account parent : [SELECT Id FROM Account WHERE Id IN :parentIds FOR UPDATE]) {
        // lock parents explicitly and predictably before child DML
    }
In practice

How Serpent prevents this

Serpent AI schedules deployments to avoid known conflicting jobs, and a locked row surfaces as a one-click retry on the same task instead of a failed release. See the Salesforce deployment error library.

Release dashboard with conflict alerts in Serpent

Prevention

Give bulk jobs and scheduled flows non-overlapping windows
Stagger scheduled batch jobs, data loads, and deployments so they don't compete for the same parent records at the same time.
Design shared singleton settings records for low contention
Avoid having many independent test classes or triggers all write to one org-wide settings record; split configuration by concern where possible.
Build automatic retry into deployment tooling for this specific error
Configure CI to detect UNABLE_TO_LOCK_ROW specifically and retry automatically once or twice, since it's one of the few Salesforce errors where a bare retry is the correct fix.
Common questions

UNABLE_TO_LOCK_ROW, answered

Is UNABLE_TO_LOCK_ROW ever caused by bad metadata?
Rarely. It is almost always a timing collision with another process, which is why simply retrying the deployment resolves most cases.
Does using FOR UPDATE in SOQL prevent this error or cause it?
FOR UPDATE deliberately acquires a lock, so it can trigger UNABLE_TO_LOCK_ROW if another transaction already holds the lock; used correctly, it makes locking explicit and predictable rather than accidental.
How many times should a pipeline retry before treating this as a real failure?
Two or three retries with a short delay between them catches the vast majority of transient lock collisions; if it still fails after that, treat it as a genuine design issue worth investigating.

Start free. No credit card, no install, no commitment.

Set up in under 15 minutes. No DevOps hire needed.

Curious about faster shipping before you dive in? Let's talk

Commitment free!