---
title: Multiple Browsers, Workers and Sharding | TestingBot
description: A suite that takes forty minutes gets run less often, and a suite that
  only runs in Chromium misses the bugs your Safari and Firefox users hit. Playwright…
source_url:
  html: https://testingbot.com/resources/courses/playwright/browsers-parallelism-and-sharding
  md: https://testingbot.com/resources/courses/playwright/browsers-parallelism-and-sharding.md
---

Course

[Playwright Tutorial: Zero to CI](https://testingbot.com/resources/courses/playwright)

Chapter 7 of 10

1. [1 Playwright Tutorial for Beginners](https://testingbot.com/resources/courses/playwright)
2. [2 Install Playwright and Run a First Test](https://testingbot.com/resources/courses/playwright/install-and-first-test)
3. [3 Locators: Find Elements the Way Users Do](https://testingbot.com/resources/courses/playwright/locators)
4. [4 Auto-Waiting and Web-First Assertions](https://testingbot.com/resources/courses/playwright/auto-waiting-and-assertions)
5. [5 Fixtures, Hooks and Logging In Once](https://testingbot.com/resources/courses/playwright/fixtures-hooks-and-authentication)
6. [6 Debugging: UI Mode, Trace Viewer, Codegen](https://testingbot.com/resources/courses/playwright/debugging-tests)
7. [7 Multiple Browsers, Workers and Sharding](https://testingbot.com/resources/courses/playwright/browsers-parallelism-and-sharding)
8. [8 Run Playwright in CI with GitHub Actions](https://testingbot.com/resources/courses/playwright/github-actions-ci)
9. [9 Run Your Playwright Suite on a Cloud Grid](https://testingbot.com/resources/courses/playwright/run-on-a-cloud-grid)
10. [10 Knowledge check](https://testingbot.com/resources/courses/playwright/knowledge-check)

[Exit course](https://testingbot.com/resources/courses)

 Chapter 7 of 10 Beginner 7 min read 3 quick checks Updated Nov 2026 

# Multiple Browsers, Workers and Sharding
On this page
1. [Projects: the same tests, different configurations](https://testingbot.com#projects-the-same-tests-different-configurations)
2. [Workers: parallelism on one machine](https://testingbot.com#workers-parallelism-on-one-machine)
3. [Sharding: parallelism across machines](https://testingbot.com#sharding-parallelism-across-machines)
4. [How much parallelism is enough?](https://testingbot.com#how-much-parallelism-is-enough)

A suite that takes forty minutes gets run less often, and a suite that only runs in Chromium misses the bugs your Safari and Firefox users hit. Playwright Test handles both with three mechanisms: **projects** decide which browsers and settings a test runs under, **workers** run tests in parallel on one machine, and **sharding** splits a run across machines.

## Projects: the same tests, different configurations[#](https://testingbot.com#projects-the-same-tests-different-configurations)

A project is a named set of options. Every test runs once per project unless you filter:

```typescript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },

    // Branded browsers installed on the machine (not the bundled builds)
    { name: 'google-chrome', use: { ...devices['Desktop Chrome'], channel: 'chrome' } },
    { name: 'edge', use: { ...devices['Desktop Edge'], channel: 'msedge' } },

    // Mobile viewport, touch and user agent emulation
    { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
    { name: 'mobile-safari', use: { ...devices['iPhone 12'] } },
  ],
});
```

The `devices` presets bundle a browser engine, viewport, user agent, device scale factor and touch support. `devices['iPhone 12']` runs WebKit with an iPhone-sized viewport and touch events; it is emulation, not an iPhone. That catches responsive layout and touch-handling bugs cheaply, but it will not catch bugs in the real Safari on iOS.

Run a subset with `--project` (repeatable, and `*` works as a wildcard):

```bash
npx playwright test --project=chromium --project=webkit
npx playwright test --project="mobile-*"
```

Projects are not only for browsers. You can have a `smoke` project with `testMatch: /.*smoke\.spec\.ts/`, a project per environment with a different `baseURL`, or the `setup` project from chapter 4.

### Browser-specific behaviour[#](https://testingbot.com#browser-specific-behaviour)

Occasionally a test cannot run on one engine, for example because it uses a Chromium-only API. Skip it explicitly so the report says so, rather than letting it fail:

```typescript
test('downloads a PDF', async ({ page, browserName }) => {
  test.skip(browserName === 'webkit', 'PDF viewer differs in WebKit');
  // ...
});
```

Use this sparingly. A skip that nobody revisits is coverage you think you have.

You want one project to run against the Google Chrome installed on the machine rather than the bundled Chromium build. What do you set?

 `browserName: 'chrome'` `...devices['Desktop Chrome']` on its own `channel: 'chrome'`

`channel` selects a branded browser. The `Desktop Chrome` preset only sets engine, viewport and user agent; it still launches the bundled Chromium.

## Workers: parallelism on one machine[#](https://testingbot.com#workers-parallelism-on-one-machine)

Playwright runs tests in separate worker processes, each with its own browser. By default it uses half your logical CPU cores. Control it in the config or on the command line:

```typescript
workers: process.env.CI ? 2 : undefined,
```

```bash
npx playwright test --workers=4
npx playwright test --workers=50%
```

Two config settings decide what can run at the same time:

- Without `fullyParallel`, **files** run in parallel with each other, but the tests inside one file run in order, in the same worker.
- With `fullyParallel: true` (the generated default), individual **tests** are distributed across workers, so even a single large file is spread out.

You can override that per file or per `describe` block:

```typescript
// Tests in this block run in order, in one worker
test.describe.configure({ mode: 'default' });
```

There is also `mode: 'serial'`, where tests run in order and a failure skips the remaining tests in the group. It exists for genuinely dependent steps, but the Playwright docs recommend making tests isolated instead, and so do we: a serial chain hides which step really broke and cannot be retried piece by piece.

### Parallel-safe test data[#](https://testingbot.com#parallel-safe-test-data)

Parallel tests break when they share mutable state on the server: the same user, the same cart, the same record. Browser contexts already isolate cookies and storage, so the remaining work is on your data:

- Create the data a test needs inside that test, with unique names (``todo-${Date.now()}``), or through an API call via the `request` fixture.
- Give each worker its own account. `testInfo.parallelIndex` is a number from `0` to `workers - 1`, unique among workers running at the same moment, and also available as `process.env.TEST_PARALLEL_INDEX`. A worker-scoped fixture can use it to pick `user-0`, `user-1` and so on.
- Never assume test order. If a test only passes after another test, it will eventually fail when the scheduler reorders them.

A test passes when you run the whole file, but fails when you run it alone with `-g`. What is the most likely cause?

 It depends on data or state left behind by an earlier test in the file `-g` disables auto-waiting Single tests run with a shorter timeout The worker count is too low

A test that only passes after another test will eventually fail when the scheduler reorders them. Make it create its own data.

## Sharding: parallelism across machines[#](https://testingbot.com#sharding-parallelism-across-machines)

Once one machine is saturated, split the suite into shards and run each on its own CI job:

```bash
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 roughly a quarter of the tests. With `fullyParallel: true`, Playwright splits at the level of individual tests, which balances shards better than splitting by file. Without it, whole files are assigned to shards, so one very large file can make one shard much slower than the others.

Each shard produces its own report, which is not much use on its own. Switch to the **blob** reporter on CI, then merge the results into one HTML report after all shards finish:

```typescript
reporter: process.env.CI ? 'blob' : 'html',
```

```bash
npx playwright merge-reports --reporter html ./all-blob-reports
```

Chapter 7 wires this into a GitHub Actions matrix.

Without `fullyParallel`, shard 3 of 4 takes three times as long as the others. What explains it?

 Shard 3 got the slowest CI runner Whole files are assigned to shards, and one very large file landed on shard 3 Sharding always gives the remainder to the third shard

Without `fullyParallel`, sharding splits by file, so one big file makes one shard slow. With it on, tests are distributed individually and the shards balance.

## How much parallelism is enough?[#](https://testingbot.com#how-much-parallelism-is-enough)

On a single machine, more workers is not always faster. Each worker runs a real browser, and once CPU or memory is saturated tests slow down and time out, which looks like flakiness. Start at the default, watch for timeouts, and lower `workers` on small CI runners. That is why the generated config uses `workers: 1` on CI: the Playwright docs recommend it for stability and reproducibility on shared CI runners, and suggest scaling out with sharding rather than piling workers onto one small machine.

Sharding moves that ceiling to the number of machines, and running browsers remotely moves it again, because the browsers no longer compete with the test runner for your CPU. In chapter 8 each worker connects to a browser on a remote grid, so worker count is limited by how many sessions your plan allows rather than by your runner's hardware. Our [parallel testing overview](https://testingbot.com/features/parallel-testing) and [parallel calculator](https://testingbot.com/support/parallel-calculator) help estimate how many sessions a suite actually needs.

For the official reference, see the [parallelism](https://playwright.dev/docs/test-parallel) and [sharding](https://playwright.dev/docs/test-sharding) guides.

[Previous · Chapter 6 Debugging: UI Mode, Trace Viewer, Codegen](https://testingbot.com/resources/courses/playwright/debugging-tests) [Next · Chapter 8 Run Playwright in CI with GitHub Actions](https://testingbot.com/resources/courses/playwright/github-actions-ci)

On this page

1. [Projects: the same tests, different configurations](https://testingbot.com#projects-the-same-tests-different-configurations)
2. [Workers: parallelism on one machine](https://testingbot.com#workers-parallelism-on-one-machine)
3. [Sharding: parallelism across machines](https://testingbot.com#sharding-parallelism-across-machines)
4. [How much parallelism is enough?](https://testingbot.com#how-much-parallelism-is-enough)

Certification

This course has a free, hands-on certificate.

[How it works](https://testingbot.com/resources/courses/playwright/certification)
