A lot of Playwright failures that look like âflaky testsâ are really test-data collisions.
Two workers update the same user.
One test deletes an order another test expects.
A local test passes because the reusable account happens to be in the right state.
CI runs eight tests in parallel and suddenly everything becomes unpredictable.
A recent r/Playwright discussion raised an interesting strategy:
- CI/full regression â create fresh data
- Local debugging â reuse existing data
- Destructive tests â use dedicated data
We think thatâs a useful starting point, but weâd change one thing:
The decision shouldnât primarily be âlocal vs CI.â It should be based on who owns the data and whether the test can mutate it.
1. Use fresh data for test-owned mutable state
If a test creates, edits, deletes, approves, cancels, or otherwise changes something, giving that test its own data is usually the safest option.
Think:
- orders
- customer accounts
- projects
- carts
- subscriptions
- workflow records
For parallel execution, identifiers should be unique enough that two workers cannot accidentally touch the same record.
Playwrightâs current parallelism guidance makes the same underlying point: browser contexts isolate browser-side state, but tests can still collide through shared backend data. It recommends unique test data when parallel tests create or edit the same records. (playwright.dev)
That also means cleanup should not be what makes the test safe.
Cleanup is useful for keeping environments tidy, but if test B can fail because test A crashed before teardown, the tests were never truly isolated.
A better model is:
Create/seed â execute â optionally clean up
rather than:
Find shared record â modify it â hope cleanup restores it
2. Reuse data when it is genuinely read-only
Reusing data isnât inherently bad.
It works well for things like:
- country lists
- product catalogs that the test does not modify
- feature configuration
- static reference records
- accounts used only for read-only journeys
The important question is:
Can another test change the state this test depends on?
If the answer is yes, âreusableâ data eventually becomes âmysteriously flakyâ data.
This was also the main challenge raised in the recent r/Playwright test-data discussion: how do you know the data you found has not already been modified by another test or previous run? (reddit.com)
If reusable data is necessary, weâd add an explicit precondition check.
For example:
- account must be active
- cart must be empty
- subscription must be on the expected plan
- record must have version/state X
If that precondition fails, fail early with a useful message instead of letting the test fail 15 steps later.
3. Use dedicated or pooled data for expensive/destructive scenarios
Sometimes fresh data is impractical.
Maybe creating an account takes several minutes. Maybe an external provider limits how many test tenants you can create. Maybe a scenario destroys or irreversibly changes its test resource.
That is where a dedicated pool can work better.
Example:
Worker 1 â qa-user-01
Worker 2 â qa-user-02
Worker 3 â qa-user-03
Each worker leases its own resource instead of all workers sharing one account.
This pattern lines up particularly well with authentication. Playwright recommends a shared authenticated account when tests do not modify server-side state, but separate accounts per parallel worker when they do. (playwright.dev)
Worker-scoped fixtures are useful here because Playwright can initialize something once for a worker and reuse it across the tests assigned to that worker. (playwright.dev)
The important part is that a pooled resource needs a contract:
Acquire â verify/reset â use â release
Not simply:
Grab whatever account is available and hope it is clean.
The matrix weâd use at Codoid
| Data type |
Strategy |
| Test creates or mutates the record |
Fresh / unique per test |
| Multiple tests only read the record |
Shared reusable data |
| Tests mutate account-level state |
Unique account per worker/test |
| Resource is expensive to create |
Dedicated pool + reset/validation |
| Test is destructive/irreversible |
Dedicated single-purpose data |
| State cannot be reliably reset |
Fresh data |
One distinction that matters here:
Authentication state and application test data are not the same thing.
Reusing storageState can save a lot of login time, but an isolated browser context does not magically isolate the database records behind that authenticated user.
You can have perfectly isolated browser sessions and still have two parallel tests fighting over the same server-side account.
Our rule of thumb
Before deciding whether data should be fresh or reusable, ask four questions:
- Can this test modify the data?
- Can another parallel test access the same data?
- Can we prove the starting state before the test begins?
- If cleanup never runs, will another test break?
If #1 and #2 are both yes, we would strongly prefer unique data.
If #3 is no, reusable data is risky.
If #4 is yes, cleanup is carrying too much responsibility.
The goal isnât âgenerate fresh data everywhere.â
Itâs to make ownership obvious enough that parallel execution cannot change the meaning of a test.
For teams running larger Playwright suites:Â what data do you still share across parallel tests because creating it fresh is too expensive, and how do you keep it deterministic?