<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kamal Thakur</title>
    <description>The latest articles on DEV Community by Kamal Thakur (@kamal_thakur).</description>
    <link>https://dev.to/kamal_thakur</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3814201%2F91ac3b05-94cc-4883-b464-caf0d5a1a3e6.jpg</url>
      <title>DEV Community: Kamal Thakur</title>
      <link>https://dev.to/kamal_thakur</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamal_thakur"/>
    <language>en</language>
    <item>
      <title>The Hidden Salesforce Bottleneck Slowing Down Your Team</title>
      <dc:creator>Kamal Thakur</dc:creator>
      <pubDate>Mon, 15 Jun 2026 13:05:23 +0000</pubDate>
      <link>https://dev.to/kamal_thakur/the-hidden-salesforce-bottleneck-slowing-down-your-team-5a3e</link>
      <guid>https://dev.to/kamal_thakur/the-hidden-salesforce-bottleneck-slowing-down-your-team-5a3e</guid>
      <description>&lt;p&gt;Every Salesforce admin and developer I've talked to knows the feeling: it's Tuesday afternoon, you're three hours deep into manually tracing a CRUD conflict, and the feature your team actually needs to ship is still sitting untouched in the backlog.&lt;/p&gt;

&lt;p&gt;That's not a skill gap. That's not a workflow problem. That's &lt;strong&gt;org tax&lt;/strong&gt; — the invisible overhead that bleeds 12–15 hours a week from Salesforce teams, buried in manual data operations, permission audits, and metadata dependency mapping.&lt;/p&gt;

&lt;p&gt;And the frustrating part? Most of it is work that shouldn't require a developer or admin at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Org Tax Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;If you've worked in a Salesforce org of any real size, you've felt this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digging through Setup to understand why a permission set is silently breaking a field-level security rule&lt;/li&gt;
&lt;li&gt;Tracing metadata dependencies before a deployment — manually, hoping nothing is missing&lt;/li&gt;
&lt;li&gt;Asking "what exactly depends on this object?" and spending an hour in Workbench to find out&lt;/li&gt;
&lt;li&gt;Reviewing org health with no structured audit trail, just institutional memory and fingers crossed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these tasks is individually manageable. Together, they quietly consume the majority of your week — and they compound with every new admin, developer, or architect added to the team.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pattern No One Talks About
&lt;/h2&gt;

&lt;p&gt;The Salesforce community is excellent at sharing &lt;em&gt;how to do things&lt;/em&gt; — Flows, Apex patterns, LWC tricks, DevOps pipelines. Blogs like Salesforce Ben, Apex Hours, and SFDC Panther have built entire audiences on exactly that.&lt;/p&gt;

&lt;p&gt;But there's a gap in the conversation around &lt;strong&gt;what we're wasting time on&lt;/strong&gt; — the 80% of grunt work that's not in any certification curriculum and nobody blogs about because it's embarrassing to admit how manual it still is.&lt;/p&gt;

&lt;p&gt;Nobody's writing "I spent 4 hours this week manually auditing sharing rules" — but everyone is doing it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Changes When You Kill the Grunt Work
&lt;/h2&gt;

&lt;p&gt;This is where &lt;a href="https://autopex.ai/?utm_source=community&amp;amp;utm_medium=social&amp;amp;utm_campaign=twinkle" rel="noopener noreferrer"&gt;Autopex&lt;/a&gt; comes in.&lt;/p&gt;

&lt;p&gt;Autopex is built specifically for Salesforce Admins, Developers, and Architects who are tired of trading productivity for visibility. It lets you:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instantly detect and resolve CRUD conflicts&lt;/strong&gt; — instead of hunting through overlapping permission sets and profiles by hand, Autopex surfaces conflicts immediately so you can fix, not find.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get complete dependency visibility&lt;/strong&gt; — data and metadata dependencies mapped and queryable, so you know the blast radius of any change before you make it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analyze your org with natural language&lt;/strong&gt; — ask questions about your org the way you'd ask a colleague. No SOQL required. No 45-minute Workbench sessions.&lt;/p&gt;

&lt;p&gt;The result: teams using Autopex report cutting org maintenance time by up to 60%.&lt;/p&gt;

&lt;p&gt;To put that concretely — if your team is losing 15 hours a week to manual org ops, that's 780 hours a year. At 60% reduction, you get back roughly 470 hours. That's nearly three months of full-time work returned to actual development.&lt;/p&gt;




&lt;h2&gt;
  
  
  500+ Hours of Salesforce Work. Reduced to Just Minutes.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.grazitti.com/products/autopex/watch-a-demo/?utm_source=community&amp;amp;utm_medium=social&amp;amp;utm_campaign=twinkle" rel="noopener noreferrer"&gt;Watch a Demo&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What Autopex Is Not&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's worth being clear about what this isn't, because the Salesforce tooling space has a lot of noise.&lt;/p&gt;

&lt;p&gt;Autopex is not a replacement for your workflow. It doesn't swap out your CI/CD pipeline, your deployment tool (Gearset, Copado, Blue Canvas — use whatever fits), or your dev process.&lt;/p&gt;

&lt;p&gt;It eliminates the invisible layer of work &lt;em&gt;underneath&lt;/em&gt; your workflow — the part where admins and devs are context-switching into manual metadata archaeology instead of shipping features.&lt;/p&gt;

&lt;p&gt;Think of it this way: your org finally becomes legible. You stop being the org's human search engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Salesforce Admins&lt;/strong&gt; managing org health and permissions across a growing user base — Autopex gives you audit-grade visibility without the audit-grade time investment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Salesforce Developers&lt;/strong&gt; who lose hours to understanding dependency chains before deployments — Autopex maps those for you, in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;The Salesforce ecosystem has gotten remarkably good at automation. Flows are more powerful than ever, Apex patterns are well-documented, and DevOps tooling has matured significantly. But most of that progress has been in &lt;em&gt;how we build things.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The gap that remains is in &lt;em&gt;how we understand and maintain what we've already built.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Org complexity only grows. Metadata accumulates. Dependencies multiply. And the default response — "just spend more time in Setup" — doesn't scale.&lt;/p&gt;

&lt;p&gt;Autopex is a direct answer to that gap.&lt;/p&gt;




&lt;p&gt;If you're a Salesforce Admin, Developer, or Business User who's curious to see what 60% less maintenance time looks like in practice,&lt;br&gt;
check out &lt;strong&gt;&lt;a href="https://autopex.ai/?utm_source=community&amp;amp;utm_medium=social&amp;amp;utm_campaign=twinkle" rel="noopener noreferrer"&gt;Autopex&lt;/a&gt;&lt;/strong&gt; and take it for a spin.&lt;/p&gt;

</description>
      <category>salesforceadmin</category>
      <category>metadata</category>
      <category>devops</category>
      <category>salesforce</category>
    </item>
    <item>
      <title>Salesforce Record Locking and Concurrency – Salesforce Things You should Know</title>
      <dc:creator>Kamal Thakur</dc:creator>
      <pubDate>Tue, 07 Apr 2026 11:31:09 +0000</pubDate>
      <link>https://dev.to/kamal_thakur/salesforce-record-locking-and-concurrency-salesforce-things-you-should-know-50e9</link>
      <guid>https://dev.to/kamal_thakur/salesforce-record-locking-and-concurrency-salesforce-things-you-should-know-50e9</guid>
      <description>&lt;p&gt;If you build on Salesforce long enough, you will hit a lock. This post explains how Salesforce Record Locking and Concurrency work, why you see UNABLE_TO_LOCK_ROW, and how to write code that behaves correctly under load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Salesforce locks records
&lt;/h2&gt;

&lt;p&gt;In a multi user system, two updates on the same record at the same time can corrupt data. To prevent that, Salesforce uses exclusive row locks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a transaction modifies a record, it takes a lock and holds it until the transaction ends.&lt;/li&gt;
&lt;li&gt;Another transaction that tries to update the same record waits for about 10 seconds. If the lock is not released in time, Salesforce throws UNABLE_TO_LOCK_ROW.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reads operations are different. A concurrent read operation sees the last committed version, not the in progress changes. That is normal isolation, meaning uncommitted changes are never visible to other transactions. &lt;/p&gt;

&lt;h2&gt;
  
  
  Reads vs writes in plain language
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Writes (DML) take a lock. Other writers wait.&lt;/li&gt;
&lt;li&gt;Reads (plain SOQL) do not lock and do not wait. They return the last committed data, which can be stale relative to an in flight update.&lt;/li&gt;
&lt;li&gt;Reads with FOR UPDATE ask for the same exclusive lock that DML uses. If a lock is held, the query waits. When it acquires the lock, it reads the freshest committed data and keeps the lock for the rest of the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quick comparison&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxitckfxuzxfvmn97cbcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxitckfxuzxfvmn97cbcs.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The classic race condition Salesforce Record Locking
&lt;/h2&gt;

&lt;p&gt;Start with an Opportunity where Amount = 100.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User A edits the Opportunity in the UI and saves Amount = 150. The write has started but is not committed yet. A holds the lock.&lt;/li&gt;
&lt;li&gt;User B triggers a process to add 30. B runs a plain SOQL query and reads Amount = 100 because A’s change is not committed.&lt;/li&gt;
&lt;li&gt;B sets 100 + 30 = 130 and tries to update. B waits for A’s lock.&lt;/li&gt;
&lt;li&gt;When A commits, the row is 150. B’s pending update still writes 130, which is wrong. The expected result was 180.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fix: make B read using FOR UPDATE so B waits, then reads the fresh value, then writes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9w9az4umsmbymkw2ituf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9w9az4umsmbymkw2ituf.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The right way to read before you write
&lt;/h2&gt;

&lt;p&gt;Use FOR UPDATE when your logic must read a value and then write a value based on it, especially for money or counters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apex"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="kd"&gt;sharing&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OpportunityService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Safely increment Amount by `delta` using FOR UPDATE&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;incrementAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="n"&gt;oppId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Simple retry for transient lock contention&lt;/span&gt;
        &lt;span class="n"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;maxAttempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;maxAttempts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Opportunity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;
                    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Opportunity&lt;/span&gt;
                    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;oppId&lt;/span&gt;
                    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;
                &lt;span class="p"&gt;];&lt;/span&gt;
                &lt;span class="n"&gt;Decimal&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;update&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// holds the lock until commit&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// success&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DmlException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Lock timeout or deadlock. Retry a couple of times.&lt;/span&gt;
                &lt;span class="kt"&gt;Boolean&lt;/span&gt; &lt;span class="n"&gt;isLockIssue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;UNABLE_TO_LOCK_ROW'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isLockIssue&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;maxAttempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="c1"&gt;// Optional: requeue work asynchronously instead of hot looping&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What this does:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The FOR UPDATE query waits if the record is locked.&lt;/li&gt;
&lt;li&gt;When the query returns, you have the lock and a fresh value.&lt;/li&gt;
&lt;li&gt;Your subsequent DML keeps the lock until commit, preventing other writers from sneaking in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical guidance for Salesforce Record Locking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep transactions short. Do not do heavy work between query and DML. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid long loops, large callouts, and complex triggers while holding locks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move DML to the end. Gather changes, then update once. This reduces lock time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use FOR UPDATE only when needed. Do not sprinkle it everywhere. Use it for read then write patterns where correctness matters, like financial amounts or inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be mindful of data skew. Avoid relating more than 10,000 child records to a single parent in lookups. Skew increases the chance of contention.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle lock errors. Catch UNABLE_TO_LOCK_ROW. Either retry a few times or requeue the work with Queueable so it runs later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Batch safely. In batch or flows that touch many related rows, group by parent to reduce cross record contention.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design idempotent operations. If a retry runs twice, it should not corrupt totals.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Debugging checklist for Salesforce Record Locking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Do you read a value and then write based on that value? If yes, consider FOR UPDATE.&lt;/li&gt;
&lt;li&gt;Are you doing DML in multiple places in a single transaction? Consolidate.&lt;/li&gt;
&lt;li&gt;Are you touching hot rows such as the same parent, the same owner, or the same counter object from many jobs? Stagger or shard the updates.&lt;/li&gt;
&lt;li&gt;Are long running triggers, workflows, or flows holding locks? Trim the work or move it async.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Salesforce Record Locking and Concurrency are there to protect your data. Plain SOQL reads last committed data and does not wait. DML and FOR UPDATE take locks and wait. When you must read then write correctly under contention, query with FOR UPDATE, keep the transaction short, and update once. Handle UNABLE_TO_LOCK_ROW with small retries or by deferring work.&lt;/p&gt;

&lt;p&gt;That is the stable pattern that keeps totals correct and errors rare.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>salesforce</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
