CI/CD October 12, 2026 6 min read

Playwright Sharding vs Workers: CI Setup Guide

Workers run tests in parallel on one machine. Shards split the suite across many machines. Combine them and a 40-minute suite can finish in minutes. This guide explains the difference, shows working pipeline configs for GitHub Actions, GitLab CI, Jenkins and Azure DevOps, and covers merging the reports back into one.

As a suite grows, CI time grows with it. Turning up workers helps until the machine runs out of CPU and memory. After that, the only way to go faster is more machines — which is exactly what sharding does.


Playwright Workers vs Shards

WorkersShards
What it isParallel worker processes on one machineSlices of the suite on separate machines
Configure withworkers in config or --workers=4--shard=1/4 on each CI job
Limited byCPU cores and memory of the runnerHow many CI jobs you can run at once
ReportsOne report automaticallyOne per shard — merge them afterwards

They stack: four shards with two workers each run up to eight tests at a time. For tuning workers on a single machine, see our parallel testing guide.

Playwright Sharding Basics

Pass --shard=x/y, where y is the total number of shards and x is the one this machine should run:

Terminal
npx playwright test --shard=1/4
npx playwright test --shard=2/4
npx playwright test --shard=3/4
npx playwright test --shard=4/4

Each command runs a different quarter of the suite. In CI, you run these as four parallel jobs.

Balancing Shards with fullyParallel

How Playwright splits the suite depends on fullyParallel:

  • With fullyParallel: true — tests are split at the individual test level, so shards come out evenly balanced.
  • Without it — tests are split at the file level. One huge spec file can make its shard much slower than the rest, so keep files small and similar in size.
  • Tests marked test.skip() or test.fixme() do not run, so they do not count toward balancing.
playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  fullyParallel: true,
  // blob reports can be merged after sharding; keep html locally
  reporter: process.env.CI ? 'blob' : 'html',
});

Playwright Sharding in GitHub Actions

This is the workflow from the official Playwright docs. A matrix starts four shard jobs, each uploads a blob report, and a final job merges them into one HTML report:

.github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  playwright-tests:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4]
        shardTotal: [4]
    steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-node@v6
      with:
        node-version: lts/*
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
    - name: Upload blob report to GitHub Actions Artifacts
      if: ${{ !cancelled() }}
      uses: actions/upload-artifact@v4
      with:
        name: blob-report-${{ matrix.shardIndex }}
        path: blob-report
        retention-days: 1

  merge-reports:
    if: ${{ !cancelled() }}
    needs: [playwright-tests]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-node@v6
      with:
        node-version: lts/*
    - name: Install dependencies
      run: npm ci
    - name: Download blob reports from GitHub Actions Artifacts
      uses: actions/download-artifact@v5
      with:
        path: all-blob-reports
        pattern: blob-report-*
        merge-multiple: true
    - name: Merge into HTML Report
      run: npx playwright merge-reports --reporter html ./all-blob-reports
    - name: Upload HTML report
      uses: actions/upload-artifact@v4
      with:
        name: html-report--attempt-${{ github.run_attempt }}
        path: playwright-report
        retention-days: 14

fail-fast: false matters. Without it, one failing shard cancels the others and you lose most of the results.

New to Actions? Start with our Playwright GitHub Actions guide.

Playwright Sharding in GitLab CI

GitLab's parallel keyword starts N copies of a job and sets CI_NODE_INDEX (1-based) and CI_NODE_TOTAL — a perfect fit for --shard:

.gitlab-ci.yml
stages: [test, report]

playwright:
  stage: test
  image: mcr.microsoft.com/playwright:v1.64.0-noble   # match your @playwright/test version
  parallel: 4
  script:
    - npm ci
    - npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
  artifacts:
    when: always
    paths: [blob-report]
    expire_in: 1 day

merge-reports:
  stage: report
  image: mcr.microsoft.com/playwright:v1.64.0-noble
  when: always
  script:
    - npm ci
    - mkdir -p all-blob-reports && cp blob-report/*.zip all-blob-reports/ || true
    - npx playwright merge-reports --reporter html ./all-blob-reports
  artifacts:
    when: always
    paths: [playwright-report]

Blob files from parallel jobs have unique names, so GitLab can collect them into one blob-report folder for the merge job. Keep the Docker image tag in sync with your installed Playwright version.

Playwright Sharding in Jenkins

In a declarative pipeline, use parallel stages — one per shard. Each stage needs an agent so the shards really run on separate executors:

Jenkinsfile
pipeline {
  agent none
  stages {
    stage('Playwright') {
      parallel {
        stage('Shard 1') {
          agent any
          steps {
            sh 'npm ci && npx playwright install --with-deps'
            sh 'npx playwright test --shard=1/3'
          }
          post { always { stash name: 'blob1', includes: 'blob-report/**', allowEmpty: true } }
        }
        stage('Shard 2') {
          agent any
          steps {
            sh 'npm ci && npx playwright install --with-deps'
            sh 'npx playwright test --shard=2/3'
          }
          post { always { stash name: 'blob2', includes: 'blob-report/**', allowEmpty: true } }
        }
        stage('Shard 3') {
          agent any
          steps {
            sh 'npm ci && npx playwright install --with-deps'
            sh 'npx playwright test --shard=3/3'
          }
          post { always { stash name: 'blob3', includes: 'blob-report/**', allowEmpty: true } }
        }
      }
    }
    stage('Merge reports') {
      agent any
      steps {
        dir('all-blob-reports') {
          unstash 'blob1'
          unstash 'blob2'
          unstash 'blob3'
        }
        sh 'npm ci'
        sh 'npx playwright merge-reports --reporter html ./all-blob-reports/blob-report'
        archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true
      }
    }
  }
}

If a shard fails, the pipeline stops before the merge stage — add catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') around the test step if you always want the merged report. For the base Jenkins setup, see our Playwright Jenkins tutorial.

Playwright Sharding in Azure DevOps

Azure Pipelines can fan out a job with strategy: parallel. Each copy knows its position through predefined variables:

azure-pipelines.yml
jobs:
- job: playwright
  strategy:
    parallel: 4
  pool:
    vmImage: ubuntu-latest
  steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '22.x'
  - script: npm ci
  - script: npx playwright install --with-deps
  - script: npx playwright test --shard=$(System.JobPositionInPhase)/$(System.TotalJobsInPhase)
    env:
      CI: 'true'
  - publish: blob-report
    artifact: blob-report-$(System.JobPositionInPhase)
    condition: always()

Add a second job that depends on playwright, downloads all blob-report-* artifacts into one folder, and runs merge-reports just like the GitHub example.

Merging Sharded Reports into One

Each shard writes a blob-report folder. Once all shards finish, collect the blob files into one folder and run:

Terminal
npx playwright merge-reports --reporter html ./all-blob-reports

The result is a single playwright-report with every test from every shard, including traces and screenshots. You can merge to other formats too, for example --reporter junit for CI dashboards. Our reporting tools guide covers the options.

How Many Shards Should You Use?

  • Start from your slowest acceptable run time. If the suite takes 40 minutes on one machine and you want 10, start with 4 shards.
  • Remember the fixed cost. Every shard repeats checkout, npm ci and browser install — often 1–2 minutes. Past a point, more shards add cost without saving time.
  • Use workers too. A 4-core runner can usually run 2–4 workers; shards multiply that.
  • Watch for imbalance. If one shard is always much slower, turn on fullyParallel or split its big spec files.
  • Retries stay inside each shard. A failed test retries on the same machine, so flaky tests can still slow one shard down — fix them with our flaky tests guide.

Frequently Asked Questions

What is the difference between Playwright sharding and workers?

Workers are parallel processes on one machine, set with workers or --workers. Sharding splits the suite across separate machines with --shard=x/y. You can combine both.

Can I use sharding and workers together?

Yes. Each shard still uses the workers setting, so 4 shards with 2 workers each run up to 8 tests at the same time.

Why are my Playwright shards unbalanced?

Without fullyParallel: true, Playwright splits by file, so one large spec file makes its shard slow. Enable fullyParallel or split large files into smaller ones.

How do I merge Playwright reports from multiple shards?

Set reporter: 'blob' in CI, collect every shard's blob-report files into one folder, then run npx playwright merge-reports --reporter html ./all-blob-reports.

How do retries work with sharding?

Retries happen inside the shard that ran the test. The merged report shows each test's attempts, so flaky tests are still easy to spot.


Asim Noaman - Playwright and Claude AI course instructor

Asim Noaman

Senior QA Automation Engineer & AI Testing Specialist

With years of hands-on experience building test automation frameworks for production applications, Asim specializes in combining traditional QA methodologies with cutting-edge AI tools. He has helped teams adopt Playwright and AI-driven testing workflows to ship faster with fewer bugs.

Udemy Instructor Published course author
Playwright + AI Expert Specialized in AI-powered QA
Production Experience Enterprise-grade frameworks
Connect on LinkedIn

Complete Course

Take Your Playwright Suite to Production CI

The complete Udemy course covers parallel runs, CI/CD pipelines and reporting hands-on — plus AI-powered test generation and maintenance with Claude.

  • Parallel workers and CI pipelines
  • GitHub Actions end to end
  • Reports teams actually read
  • AI-assisted test maintenance
Enroll Now on Udemy →