Playwright runs tests in parallel across worker processes by default, each worker owning an isolated browser. Sharding splits the whole suite across multiple machines/CI jobs. Together they cut wall-clock time dramatically for large suites.
By default, files run in parallel across workers (roughly one per CPU core); tests within a single file run sequentially unless you opt into test.describe.configure({ mode: 'parallel' }). Each worker is a separate process with its own browser, so tests are isolated as long as they don't share external state (same DB row, same user account). Sharding (--shard=1/4) partitions the test list into N slices so four CI machines each run a quarter, and you merge the blob reports afterward into one HTML report. The main caveats: ensure test data isolation (unique users/records per test or per worker) so parallel tests don't collide, and mark truly order-dependent tests as serial deliberately.
A 900-test suite took 50 minutes on one machine. Running with 6 workers locally brought it to ~10 minutes; on CI, --shard across 5 jobs (each with workers) brought wall-clock time under 3 minutes, with the five blob reports merged into a single HTML report for reviewers.
# Local: run with 6 workers
npx playwright test --workers=6
# Opt a file into intra-file parallelism
# test.describe.configure({ mode: 'parallel' });
# CI: shard across 5 machines (matrix job sets shardIndex)
npx playwright test --shard=1/5
npx playwright test --shard=2/5
# ...
# Merge the per-shard blob reports into one HTML report
npx playwright merge-reports --reporter=html ./all-blob-reportsScenario: After enabling parallel workers, ~5% of tests fail intermittently with 'record already exists' or wrong data. Sequentially they all pass. What's the root cause and how do you fix it without giving up parallelism?