📖 The Story: The Retry That Poisoned the Suite

A team had a flaky test that failed ~10% of the time. When it failed, Playwright retried it immediately in the next available worker. But the retry sometimes failed too — not because the test was broken, but because the failed first attempt had left a database connection open, and the retry’s queries timed out waiting for the lock.

The team tried increasing retries to 3, but that made it worse — each retry interfered with the next, and the suite’s overall pass rate dropped because the flaky test’s retries were poisoning other tests sharing the database.

They tried isolating the flaky test in its own project, but that required maintaining a separate config and a deny-list of “do not run with other tests” files.

retryStrategy: 'isolated' in 1.62 fixes this. Failed tests retry at the end of the suite, one by one in a single worker, so they can’t interfere with other tests.

🎯 Why It Matters

🔒

No Interference

Retries run at the end in a single worker. Failed first attempts can’t poison other tests.

🔍

Forensics

Perfect for nightly flaky-test hunting — see if a test fails consistently when isolated.

⚖️

Clean State

Each retry gets a fresh worker. No leftover state from the previous attempt’s failure.

💾

Deterministic

Retries run sequentially, not in parallel — easier to reason about and debug.

🌍 Real World Example

A team’s nightly flaky-test hunt runs 500 tests with 3 retries. With the default 'immediate' strategy, a flaky test’s retries run as soon as a worker is free, often overlapping with other tests that share a database. With retryStrategy: 'isolated', all 500 tests run first (no retries), then any failures retry one-by-one at the end in a single worker. The flaky test’s retries can’t interfere with other tests, and the team gets a clean signal: “this test failed 3/3 times when isolated — it’s genuinely broken, not environmentally flaky.”

🧒 Explain Like I'm 10

Imagine you’re taking a test in a classroom. If you fail a question, the teacher lets you retry it immediately — but the kid next to you is also retrying, and you keep bumping elbows. You both fail again because you’re distracting each other.

Now, the teacher says: “everyone finish the test first. If anyone failed a question, they can retry it at the end, alone in the room.” No more bumping elbows — each retry happens in isolation, so you either pass on your own merits or fail because the question is genuinely too hard.

🎓 Professional Explanation

Playwright’s default retry strategy is 'immediate' — when a test fails, it retries as soon as a worker is free. This is fast (retries overlap with other tests) but can cause interference: a failed first attempt may leave shared state (database connections, file locks, environment variables) that poisons the retry or neighboring tests.

Playwright 1.62 adds retryStrategy: 'isolated'. With this strategy, all tests run first without retries. After the suite completes, any failed tests retry one-by-one in a single worker. Each retry gets a fresh worker, eliminating interference from the previous attempt’s failure. This is slower (retries are sequential at the end) but produces cleaner signals for flaky-test forensics.

📊 The Flow

Immediate vs Isolated Retry Strategy

Immediate (default): Test fails → retries ASAP in next free worker
⬇️
Retry may overlap with other tests → interference risk
⬇️
Isolated: All tests run first (no retries)
⬇️
Failed tests retry at end, one-by-one in a single worker
⬇️
Each retry gets a fresh worker → no interference, clean signal

⚙️ retryStrategy: 'isolated'

Set retryStrategy in your playwright.config.ts. The default is 'immediate'; set it to 'isolated' for flaky-test forensics.

typescript
class=class="tk-str">"tk-com">// playwright.config.ts
import { defineConfig } from class="tk-str">'@playwright/test';

export default defineConfig({
  retries: 2,
  retryStrategy: class="tk-str">'isolated',  class=class="tk-str">"tk-com">// new in 1.62
});

With 'isolated', all tests run first without retries. After the suite completes, any failed tests retry one-by-one in a single worker. Each retry gets a fresh worker, eliminating interference.

typescript
class=class="tk-str">"tk-com">// Per-project strategy: immediate for PRs, isolated for nightly
export default defineConfig({
  projects: [
    {
      name: class="tk-str">'pr',
      testMatch: class="tk-str">'**/*.spec.ts',
      retries: 1,
      retryStrategy: class="tk-str">'immediate',  class=class="tk-str">"tk-com">// fast feedback for PRs
    },
    {
      name: class="tk-str">'nightly',
      testMatch: class="tk-str">'**/*.spec.ts',
      retries: 3,
      retryStrategy: class="tk-str">'isolated',  class=class="tk-str">"tk-com">// clean signal for flaky hunting
    },
  ],
});

Use different strategies per project. PRs want fast feedback (immediate), nightly flaky-hunts want clean signals (isolated). This is the recommended setup for teams that take flakiness seriously.

typescript
class=class="tk-str">"tk-com">// CLI override
class=class="tk-str">"tk-com"># Run with isolated retries for one-off flaky hunting
npx playwright test --retries=3 --retry-strategy=isolated

class=class="tk-str">"tk-com"># Or via env var in CI
RETRY_STRATEGY=isolated npx playwright test

You can override the config via CLI (--retry-strategy=isolated) or environment variable. Useful for one-off flaky-test hunts without changing the config file.

🔄 Before vs After

Before: Immediate retries (default, all versions)

typescript
export default defineConfig({
  retries: 2,
  class=class="tk-str">"tk-com">// retryStrategy defaults to class="tk-str">'immediate'
});

class=class="tk-str">"tk-com">// Test fails → retries ASAP in next free worker
class=class="tk-str">"tk-com">// Retry may overlap with other tests sharing a database
class=class="tk-str">"tk-com">// Failed first attempt's state may poison the retry

Immediate retries are fast but can cause interference. A failed first attempt may leave shared state (DB connections, file locks) that poisons the retry or neighboring tests.

After: Isolated retries (1.62+)

typescript
import { defineConfig } from class="tk-str">'@playwright/test';

export default defineConfig({
  retries: 2,
  retryStrategy: class="tk-str">'isolated',
});

class=class="tk-str">"tk-com">// All tests run first (no retries)
class=class="tk-str">"tk-com">// Failed tests retry at end, one-by-one in a single worker
class=class="tk-str">"tk-com">// Each retry gets a fresh worker → no interference

Isolated retries are slower (sequential at the end) but produce clean signals. Each retry gets a fresh worker, so a failed first attempt can’t poison the retry. Perfect for flaky-test forensics.

⚠️ Gotcha

Isolated retries extend total suite wall-clock time. With 'immediate', retries overlap with other tests. With 'isolated', retries run sequentially at the end. For a suite that takes 10 minutes with immediate retries, isolated retries can push that to 12–15 minutes if multiple tests fail. Reserve isolated retries for nightly flaky-hunt jobs; keep immediate for per-PR CI gates.

⚠️ Common Mistakes

Mistake 1: Using isolated retries for PR CI

Isolated retries are slower because they run sequentially at the end. For PR CI, developers want fast feedback — use the default 'immediate' strategy. Reserve 'isolated' for nightly flaky-hunt jobs.

Mistake 2: Expecting isolated retries to fix flaky tests

Isolated retries give you a cleaner signal about whether a test is genuinely flaky, but they don’t fix the underlying flakiness. If a test fails 3/3 times with isolated retries, it’s genuinely broken — fix the test or the code, don’t just add more retries.

Mistake 3: Not setting retries high enough for isolated

With isolated retries, you want enough attempts to distinguish “flaky” from “broken.” A test that fails 1/3 times is flaky; a test that fails 3/3 times is broken. Use retries: 3 minimum for isolated strategy so you get this signal.

✅ Best Practices

  1. Use 'immediate' for PR CI — fast feedback for developers.
  2. Use 'isolated' for nightly flaky-hunts — clean signal, no interference.
  3. Set retries: 3 minimum for isolated to distinguish flaky from broken.
  4. Don’t use isolated to “fix” flakiness — it gives signal, not a cure.
  5. Use per-project strategies to serve both PRs and nightly from one config.

🏗️ Senior Engineer Deep Dive

Why isolated retries produce cleaner signals

With immediate retries, a failed first attempt may leave shared state: an open database transaction, a file lock, a modified environment variable, a cached value in a service. The retry runs in a fresh worker, but the shared state persists across workers. With isolated retries, all tests complete first (so the shared environment is back to baseline), then each retry runs in a single worker with a fresh setup. If a test fails 3/3 times in isolation, you know it’s the test that’s broken, not environmental interference.

Combining isolated retries with sharding

In a sharded CI run, each shard is independent — isolated retries within a shard don’t affect other shards. This means you can run isolated retries on a known-flaky shard without slowing down the rest of the suite. Configure the flaky shard’s project with retryStrategy: 'isolated' and the stable shards with 'immediate'. The stable shards finish fast; the flaky shard takes longer but produces a clean signal.

💼 Interview Questions

Beginner
What does retryStrategy: 'isolated' do?
Show Answer
It changes the retry behavior so that all tests run first without retries, then any failed tests retry one-by-one at the end in a single worker. Each retry gets a fresh worker, eliminating interference from the previous attempt's failure.
Intermediate
When should you use 'isolated' vs 'immediate'?
Show Answer
Use 'immediate' (the default) for PR CI where fast feedback matters. Use 'isolated' for nightly flaky-test hunts where you want a clean signal about whether a test is genuinely broken vs environmentally flaky. Isolated is slower but produces less interference.
Advanced
Why do isolated retries produce cleaner flaky-test signals?
Show Answer
With immediate retries, a failed first attempt may leave shared state (DB connections, file locks, env vars) that poisons the retry. With isolated retries, all tests complete first (shared environment returns to baseline), then each retry runs in a single fresh worker. If a test fails 3/3 times in isolation, it's genuinely broken, not environmentally flaky.
Scenario
Your nightly CI shows a test as flaky (passes sometimes, fails sometimes). How do you determine if it's genuinely broken or environmentally flaky?
Show Answer
Set retryStrategy: 'isolated' with retries: 3 for the nightly run. All tests run first without retries, then failures retry one-by-one in a single worker. If the test fails 3/3 times in isolation, it's genuinely broken. If it passes 2/3 times, it's environmentally flaky — investigate shared state, timing, or external dependencies.

🏋️ Practical Exercise

🎯 Hands-On Practice medium

Compare Immediate vs Isolated

  1. Pick a known-flaky test in your suite
  2. Run it 3 times with immediate retries: npx playwright test flaky.spec --retries=3
  3. Note the pass/fail pattern and total time
  4. Now run with isolated retries: npx playwright test flaky.spec --retries=3 --retry-strategy=isolated
  5. Compare the pass/fail pattern and total time
  6. If the test passes with isolated but fails with immediate, it’s environmentally flaky (shared state issue)

🚀 Mini Project

🏗️ The Nightly Flaky Dashboard

  1. Create a separate Playwright project called “nightly” with retryStrategy: 'isolated' and retries: 3
  2. Run it nightly via GitHub Actions cron: 0 4 * * *
  3. Write a custom reporter that logs each test’s retry outcome (e.g., “3/3 failed”, “2/3 passed”)
  4. After a week, identify tests that failed 3/3 more than once — these are genuinely broken
  5. Identify tests that passed 2/3+ — these are environmentally flaky
  6. File issues for both categories with the retry data as evidence

📝 Quiz

Test your understanding. Click an option to check your answer.

1. What is the default retryStrategy?
A) 'isolated'
B) 'immediate'
C) 'none'
D) 'parallel'
Answer: B — The default is 'immediate' — failed tests retry as soon as a worker is free, overlapping with other tests.
2. When do retries run with 'isolated' strategy?
A) Immediately after each failure
B) At the end of the suite, one-by-one in a single worker
C) In parallel with other tests
D) Never — isolated disables retries
Answer: B — With 'isolated', all tests run first without retries, then failed tests retry one-by-one at the end in a single worker.
3. Why do isolated retries produce cleaner signals?
A) They run faster
B) Each retry gets a fresh worker with no interference from previous failures
C) They skip setup
D) They use a different test runner
Answer: B — With isolated retries, all tests complete first (shared environment returns to baseline), then each retry runs in a fresh worker. A failed first attempt can't poison the retry.
4. Which strategy should you use for PR CI?
A) 'isolated'
B) 'immediate'
C) Neither — disable retries for PRs
D) It doesn't matter
Answer: B — Use 'immediate' for PR CI — developers want fast feedback. Isolated is slower (sequential at the end) and better suited for nightly runs.
5. Which strategy should you use for nightly flaky-hunts?
A) 'isolated'
B) 'immediate'
C) Neither — run with 0 retries
D) 'parallel'
Answer: A — Use 'isolated' for nightly flaky-hunts — clean signal, no interference. If a test fails 3/3 in isolation, it's genuinely broken.
6. Which Playwright version introduced retryStrategy: 'isolated'?
A) 1.60
B) 1.61
C) 1.62
D) 1.63
Answer: C — retryStrategy: 'isolated' shipped in Playwright 1.62 (July 24, 2026).
7. Does isolated retries fix flaky tests?
A) Yes, it automatically fixes them
B) No — it gives a cleaner signal about flakiness, but doesn't fix the underlying issue
C) Only on Chromium
D) Only if combined with sharding
Answer: B — Isolated retries give you a cleaner signal (is the test genuinely broken or environmentally flaky?), but they don't fix the test. You still need to fix the underlying issue.
8. How many retries should you set for isolated strategy?
A) 1
B) 2
C) 3 minimum (to distinguish flaky from broken)
D) 10
Answer: C — Use retries: 3 minimum for isolated strategy. 1/3 failures = flaky, 3/3 failures = broken. With only 1-2 retries, you can't distinguish.
9. Can you set different retryStrategies per project?
A) No, it's global only
B) Yes — set retryStrategy in each project's config
C) Only via env var
D) Only on Chromium
Answer: B — Set retryStrategy per project. Use 'immediate' for PR projects, 'isolated' for nightly projects. Both can run from the same playwright.config.ts.
10. How can you override retryStrategy via CLI?
A) You can't
B) --retry-strategy=isolated
C) --isolated
D) -R isolated
Answer: B — Use --retry-strategy=isolated (or immediate) on the CLI. Useful for one-off flaky-test hunts without changing the config file.

❓ FAQ

Q: Does retryStrategy work with sharding?

A: Yes. Each shard is independent — retryStrategy applies within each shard. You can run isolated retries on a known-flaky shard without affecting other shards. This is useful for isolating flaky tests in their own shard with isolated retries while keeping stable shards on immediate.

Q: Can I see which retry attempt failed in the report?

A: Yes. The HTML reporter shows each retry attempt as a separate entry with its status. With isolated retries, you’ll see all first attempts grouped together, then all retry attempts at the end. Custom reporters can access testInfo.retry to log which attempt failed.

Q: Does isolated retries affect the test timeout?

A: No. The test timeout (testConfig.timeout) applies to each attempt individually. Isolated retries just change when retries happen, not how long each one can run. A 30-second timeout still applies to each of the 3 retry attempts.

📦 Summary

🎯 Key Takeaways

  • retryStrategy: 'isolated' runs all tests first, then retries failures one-by-one at the end.
  • Use for nightly flaky-hunts — clean signal, no interference from previous failures.
  • Use 'immediate' (default) for PR CI — fast feedback for developers.
  • Set retries: 3 minimum for isolated to distinguish flaky (1/3) from broken (3/3).
  • Per-project strategies let you serve PRs and nightly from one config.