
Tekunda Team

Andrew Hanna

To run Apex tests in parallel without flaky failures, make every test create its own data, never write to records that exist outside the test, and generate unique values for fields like usernames. Then diagnose any remaining flake by rerunning that class on its own: if it passes alone and fails in parallel, you have an isolation problem, not a bug. Turning off parallel testing org-wide hides the symptom and slows every run.
By default, Salesforce runs asynchronous test classes concurrently, so two tests can compete for the same resource at the same moment. The failures cluster into three causes:
UNABLE_TO_LOCK_ROW, and that
limit cannot be changed, as
Xappex explains. Parent records are locked silently when master-detail children are updated, when
roll-up summaries recalculate and during sharing processing.
[email protected] at once fail with
DUPLICATE_USERNAME, a pattern
Salesforce Central documents.
@isTest(SeeAllData=true) reads and writes real records that other tests
can touch at the same time.
None of these show up when a class runs alone, which is why the suite looks random.
UNABLE_TO_LOCK_ROW,
DUPLICATE_USERNAME and other duplicate-value errors on test data point
to concurrency.
--synchronous flag runs the test methods of a single Apex class
synchronously, per the
plugin-apex documentation.
@TestSetup or a data factory and drop SeeAllData=true.
Tests that build their own data do not contend for org records.
@isTest(isParallel=true) to flag classes that can run in parallel
without the default concurrency limits, as
FishOfPrey covers. Add it only to
classes that pass repeatedly in parallel runs.
Only as a stopgap. The setting lives under Setup, Apex Test Execution, Options, and runs asynchronous tests one at a time. It removes concurrency flakes, but in orgs with many test classes a full run can take far longer. Some tools depend on the same switch: Gearset's documentation notes its test monitors use the Tooling API and therefore run tests in parallel unless you enable it.
Treat the checkbox as a debt marker. Turn it on to unblock a release, then fix the offending classes and turn it off again.
sf apex run test --test-level RunLocalTests gives you the parallel run
your production deploys will see.
--result-format junit --output-dir so your pipeline can track failures
per class over time, and --code-coverage to keep coverage visible.
Blind retries are tempting, but they turn real defects into green builds. The same discipline applies when you change tooling, as covered in how to switch Salesforce DevOps tools without breaking your pipeline and our guide to migrating from Gearset to Serpent without downtime.
Point-and-click releases hit the same failures, because the tests still run on deploy. Our click deploy checklist covers what to verify first, and you can browse more how-tos in SF Guides.
Tekunda is the Salesforce consulting and product company that builds Serpent, a Salesforce DevOps platform with GitHub-based source control and automated deployment pipelines. If flaky tests are stalling your releases, compare plans on our pricing page.
Does Salesforce run Apex tests in parallel by default?
Yes, asynchronous test runs execute classes concurrently unless Disable Parallel Apex Testing is enabled in Setup.
What causes UNABLE_TO_LOCK_ROW in Apex tests?
Two transactions want the same record, often a parent locked by a master-detail update, roll-up summary or sharing recalculation. The waiting one fails after 10 seconds.
Should I retry flaky Apex tests automatically?
Retry once, synchronously, and only for concurrency errors. Log every flake and fix the class rather than relying on retries.
Is isParallel=true enough to fix flaky tests?
No. It only marks a class as parallel-safe. The test still has to create its own data and use unique values.
Commitment free!