TestKase
TestKase
|Docs
AutomateBrowserPlaywright

Running tests in parallel

Run many Playwright tests at once, keep the results together, and know what happens when you ask for more than you have.

Playwright already runs tests in parallel — it has workers built in, and each one opens its own session with us. Usually there is nothing to turn on.

Two things to get right: how many workers, and keeping the results together.

1. Choose your worker count

npx playwright test --workers=5

Or in playwright.config.ts:

export default defineConfig({
  workers: 5,
  fullyParallel: true,
});

Playwright defaults to half your CPU cores locally and one worker in CI, so a CI run is often serial without anyone noticing. Set it explicitly.

2. Give every worker the same runId

Five workers means five sessions. Without a runId that is five separate runs in your dashboard, which tells you nothing about whether your tests passed.

Use a value your CI already has — GITHUB_RUN_ID, BUILD_NUMBER, CI_PIPELINE_ID:

"testkase:options": {
  runId: process.env.GITHUB_RUN_ID ?? "local",
}
Using the @testkase CLI? It mints a run id each time you run it and passes it to every worker, so one command is already one run. Do not set runId yourself.
build does not group anything. It is a label. Sessions that share a build but no runId are still separate runs.

3. How many at once

Limit
Paid plansOne session per thread, 1 to 20 threads
Free tierNo thread limit — your remaining free minutes are the only ceiling
Over your limitWaits for one of your threads to free up, then refuses if none does

Going over your limit no longer fails straight away. The session waits for one of your own threads, and only gives up if none comes free in time — arriving as a WebSocket close 4429:

Waited, but all 5 of your parallel sessions were busy the whole time.
Close one, or raise your plan's parallel limit.

So a run with more workers than threads will mostly still finish; the extra workers wait their turn. Keep --workers at or below your thread count anyway, because waiting is slower than sizing the run correctly — and Playwright will not retry a connection refused this way.

How long it waits is the same maxQueueWaitSeconds described below, and the two waits share it: time spent waiting for a thread is time not left for waiting for a machine.

4. Why a session still waits sometimes

Being under your own limit does not mean a machine is free. Our machines have their own limit, shared with everyone, and you wait when every machine matching your request is busy. That wait is maxQueueWaitSeconds — 5 minutes by default, up to 9 minutes — and it is not billed.

Two things help more than raising that number:

Ask for a mix. Five workers all asking for one macOS version and Safari draw on a handful of machines. The same five across Chrome, Edge and Firefox on two operating systems draw on many more.

Leave room for cleaning up. A session that is still ending still holds its machine. Fire a second run immediately at the same narrow target and it queues behind the run before it.

The full picture — thread bands, per-machine ceilings, free minutes — is in Reference.

Do you also need to mark tests?

With workers, each session runs one test, so the session name is enough to read the run at a glance.

Marking tests is for the other shape — one connection running several tests in a row.