Running 100 Playwright Tests in Parallel Without Inbox Collisions

Published: (June 12, 2026 at 06:07 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

If you’ve ever tried to run a large Playwright test suite in parallel — the kind that tests email verification flows, magic links, or password resets — you’ve probably hit this problem: Two tests run at the same time. Both sign up with the same test email address. Test A waits for a verification email. Test B’s email arrives first. Test A reads it. Test B times out. The whole suite goes red, and you spend an hour debugging a race condition that only happens in CI. This is the inbox collision problem. It’s subtle, it’s intermittent, and it’s completely avoidable. Most email testing tools give you one of two options: Option 1: A single shared inbox (Mailpit, MailHog, local SMTP) Option 2: A limited pool of inboxes The real fix is simpler: one isolated inbox per test run, always. ZeroDrop generates a new inbox on every call — no shared state, no pools, no configuration: const mail = new ZeroDrop(); const inbox = mail.generateInbox(); // void-a3k9x@zerodrop-sandbox.online

Each inbox name is a random adjective + 7-character alphanumeric string. The address space is large enough that collision probability across thousands of parallel runs is effectively zero. Every test run gets a cryptographically isolated inbox that no other test can see or contaminate. This isn’t a setting you enable. It’s how the system works by default. Here’s a real example — 4 parallel workers, each running a separate auth flow test, each with its own isolated inbox: name: E2E Auth Tests (Parallel)

on: [push]

jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] # Run 4 workers in parallel

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'

  # Each worker gets its own isolated inbox
  - name: Generate isolated test inbox
    id: inbox
    uses: zerodrop-dev/create-inbox@v1

  - name: Run Playwright shard
    run: npx playwright test --shard=${{ matrix.shard }}/4
    env:
      TEST_INBOX: ${{ steps.inbox.outputs.inbox }}

Four workers. Four inboxes. Zero collisions. The zerodrop-dev/create-inbox Action runs on each worker independently — no shared state, no coordination required. The pattern scales linearly. 10 workers, 10 inboxes. 100 workers, 100 inboxes. There’s no pool to exhaust, no lock to acquire, no cleanup step between runs. // In your Playwright test — works identically across all parallel workers import { test, expect } from ‘@playwright/test’; import { ZeroDrop } from ‘zerodrop-client’;

const mail = new ZeroDrop();

// process.env.TEST_INBOX is set per-worker by the GitHub Action // Falls back to a fresh inbox when running locally const inbox = process.env.TEST_INBOX ?? mail.generateInbox();

test(‘email verification flow’, async ({ page }) => { await page.goto(‘/signup’); await page.fill(‘[name=“email”]’, inbox); await page.click(‘[type=“submit”]’);

// This worker’s inbox — no other worker can see this email const email = await mail.waitForLatest(inbox, { timeout: 15000 }); const link = email.body.match(/https?://\S+verify\S+/)?.[0]; await page.goto(link);

await expect(page).toHaveURL(‘/dashboard’); });

Each worker is completely self-contained. The test doesn’t know or care how many other workers are running. Some email testing tools cap concurrent inboxes on lower-tier plans — commonly 10 per account. If your CI matrix runs more than 10 parallel workers, which is common in enterprise pipelines, you either hit the limit and tests fail, or you upgrade to a higher tier for unlimited inboxes. ZeroDrop’s free tier has no inbox limit. Every test run generates a fresh inbox instantly, at the edge, with no network request during generation. The inbox name is computed locally on the runner — there’s nothing to hit a rate limit on. Each ZeroDrop inbox is isolated by design: Unique per run — random name generated at test start, never reused Ephemeral — auto-deleted after 30 minutes via Redis TTL Private — only accessible via the exact inbox name; no enumeration API Edge-routed — emails are caught at Cloudflare’s global edge, not a central server The 30-minute TTL means stale test data never accumulates. A test suite that ran 6 hours ago has left zero traces. A complete parallel Playwright setup with ZeroDrop, including the GitHub Actions matrix configuration and full auth flow tests: → github.com/zerodrop-dev/zerodrop-playwright-example The example uses a single worker for simplicity, but the pattern scales directly to matrix builds — just add the strategy.matrix block shown above. ZeroDrop’s free tier includes unlimited inboxes, the full SDK, and the GitHub Action — no signup required, no credit card, no paywall on the API. For teams who need custom domains, 7-day retention, and shared API keys: zerodrop.dev

0 views
Back to Blog

Related posts

Read more »

The spec is in the wrong place

My day job is at a large tech company. Hundreds of engineering teams, and every one of them is somewhere different on AI adoption. Some are still treating codin...

The Heuristics Say Don't

A culture that only records its disasters ends up with a biased archive. Wars documented, plagues chronicled, collapses catalogued. The quiet decades go unwritt...