How do Playwright's trace modes 'on' and 'retain-on-failure' differ in what survives a run?
answer
- Two halves: recording and keeping
- Same work during the test, different disposal
- One family saves disk, one saves time
- Only one family captures the real failure
basics
~10 sBoth record every test attempt, so both pay the full capture cost. The difference is afterwards: 'on' keeps every trace zip, while 'retain-on-failure' deletes the ones belonging to tests that passed.
solid answer
~40 sThe two modes are identical while the test runs — Playwright starts tracing for every attempt under both, so neither saves you recording overhead. They part company at the end of the test. `'on'` writes and keeps the zip whatever the outcome; `'retain-on-failure'` throws away the zip for a test that passed and keeps it only for failures. So `'retain-on-failure'` buys you disk and upload savings, not runtime savings, and unlike `'on-first-retry'` it captures the **original** failing attempt rather than a re-run — which is what you want when chasing a flake that will not reproduce. Playwright 1.63 also offers `'retain-on-first-failure'`, which records only the first attempt of each test and keeps it only on failure, and `'on-all-retries'`, which records retried attempts only.
code
typescript · 13 linesimport { defineConfig, devices } from '@playwright/test';
export default defineConfig({
use: { trace: 'on-first-retry' },
projects: [
{ name: 'order-tracker', use: { ...devices['Desktop Chrome'] } },
{
name: 'driver-map-flaky',
testMatch: /driver-map\.spec\.ts/,
use: { ...devices['Desktop Chrome'], trace: 'retain-on-failure' },
},
],
});go deeper
Learn the two mode families by name and what each writes to disk. The key fact to hold on to is that retain-on-failure still records every test; it just deletes the passing zips.
Explain the recording-versus-retention split precisely, and be able to place all the modes in that grid rather than reciting them as an unordered list.
Show you pick a mode from the pressure you are under — pipeline time, artefact size, or an unreproducible flake — and that you know retry-scoped modes never capture the original failing attempt.
Own the standard across projects: a default mode, named exceptions for known-flaky areas, and a rule that stops a debugging mode from leaking into every project's config.
Playwright's `trace` option has two independent halves that candidates routinely collapse into one: **when recording happens** and **which recordings are kept**. Comparing `'on'` with `'retain-on-failure'` is the cleanest way to see the split. ## Recording versus retention Under both `'on'` and `'retain-on-failure'` the runner starts tracing before the test body and stops it after. Every action gets a snapshot; every console message and network record is buffered. The work is the same, so the *runtime* cost is the same. The difference is the disposal step: - `'on'` — the zip is written to the attempt's folder under `test-results/` and attached to the result, pass or fail. - `'retain-on-failure'` — the zip is written only if the test ended in failure; on a pass it is discarded. Saying "retain-on-failure only records failures" is the classic wrong answer. It cannot know the outcome in advance, so it must record first and decide later. ## The full set of modes in Playwright 1.63 | mode | records | keeps | |---|---|---| | `'off'` | nothing | nothing | | `'on'` | every attempt | every zip | | `'retain-on-failure'` | every attempt | failures only | | `'retain-on-first-failure'` | first attempt only, not retries | failures only | | `'on-first-retry'` | the first retry only | that zip | | `'on-all-retries'` | every retry attempt | those zips | Read the table down the two right-hand columns and the design becomes obvious: the `retain-*` family optimises **storage**, the `on-*-retr*` family optimises **capture time**. ## Which pressure are you actually under? 1. **Pipeline minutes.** If tests are slow because tracing snapshots every action of a long order-tracker flow, retention modes do not help you — only recording less does, so reach for a retry-scoped mode. 2. **Artefact size and upload.** If the run is fast but the artefacts are huge, `'retain-on-failure'` is exactly right: you keep the evidence and throw away the ninety-odd percent of zips nobody will open. 3. **Flake investigation.** If a failure will not reproduce on a re-run, the retry-scoped modes are useless to you — they trace the reproduction. `'retain-on-failure'` captures the attempt that actually failed. ## A worked case A suite for a food-delivery order tracker drives live status polling and a driver map. The map test fails once a day and always passes when re-run. Under `'on-first-retry'` the team collects trace after trace of a healthy map. Switching that project to `'retain-on-failure'` costs recording time on every run but finally produces a zip of the failing attempt itself — the one where the socket update arrived late. If the recording cost of every attempt is unacceptable, `'retain-on-first-failure'` is the middle setting: it records the initial attempt of each test but not the retries, and keeps the zip only when that attempt failed. ## Configuring the choice - The mode is a `use` option, so it can differ per project, per file via `test.use`, and be overridden for one run by `npx playwright test --trace retain-on-failure`. - The object form `trace: { mode: 'retain-on-failure', screenshots: true, snapshots: true, sources: false }` sets the mode and trims what goes inside each zip, which is another way to cut size without losing the failing attempt. - `'on'` is best treated as a debugging setting you turn on deliberately for a run or a single project, not a suite default — it is the mode that quietly makes every green run expensive in both time and storage. ## Talking about it in an interview The strong answer names the split in one sentence — *both record everything; only the retention differs* — then says which pressure each family relieves, and finishes with the flake case, because that is the scenario where picking the cheap retry-scoped mode actively destroys the evidence you were trying to collect.
- Does 'retain-on-failure' make a green run any faster than 'on'?No. Both start tracing before every test and stop after it, so the snapshot and buffering work is identical. The only saving is on disk and upload, because the passing tests' zips are deleted instead of written out. If recording time is your problem, you need a mode that records fewer attempts, not one that keeps fewer files.
- What does 'retain-on-first-failure' add over 'retain-on-failure'?It records only each test's first attempt, not its retries, and still keeps the zip only when that attempt failed. You get the original failure captured, without paying to record the retry attempts as well. It is the compromise for suites that want the real failing attempt but run with several retries.
- How do you shrink traces without changing the mode?Use the object form of the option and turn off what you do not need: `trace: { mode: 'retain-on-failure', sources: false }` drops the copied test sources, and disabling `screenshots` removes the per-action image frames. Snapshots are usually the last thing to sacrifice, since they carry the page state the evidence depends on.
saying these in an interview costs you the question
- Says retain-on-failure only records failing tests
- Claims retain-on-failure speeds up green runs
- Treats trace: on as a safe suite-wide default
- Thinks retry-scoped modes capture the original failure
- Confuses the trace mode with the retries setting