We Budget 30% of Every Sprint for Flaky Tests

Table of Contents
The director didn’t say no to test maintenance. He said, “The tests are already written.” Then he approved the coverage roadmap and left the room, and I spent the next two quarters paying for a flaky test maintenance budget that existed in every way except on paper.
That is what a flaky test maintenance budget looks like when it doesn’t exist. You didn’t lose that line. You never got to argue about it, because the work is real, it happens anyway, and it comes out of the only capacity you were funded for. We now reserve 30% of every sprint for it, explicitly, on the board, in front of the product owner. Our new-test output didn’t drop. What changed is that we stopped looking slow.
Why does flaky test maintenance always lose the sprint planning argument?
Because it isn’t in the argument. Nobody rejects the maintenance ask on the merits — they reject it against an alternative, and unbudgeted work has no advocate in the room. Coverage has a roadmap, a stakeholder, and a slide. Fixing a locator that broke when marketing shipped a new nav bar has none of those, so it loses to a comparison it never entered.
Unbudgeted work doesn’t look like work — it looks like slowness
This is the part that ends QA careers. At a large North American freight company — 5 SDETs, 4 product squads, 1,140 tests across Playwright and TestNG, 36-minute pipeline — we spent an entire quarter doing flaky-test work we hadn’t asked permission for. The tests got fixed. The sprint commitments didn’t get hit: 61% of committed points landed, quarter over quarter.
Nobody read that as “they are absorbing unfunded work.” They read it as a throughput problem, and two of my SDETs got throughput language in their performance reviews for time they spent keeping the suite honest. Work you do without a budget line is not invisible — it is visible as a defect in you.
How much sprint capacity should a flaky test maintenance budget get?
Start at 30% of QA capacity, then earn the right to lower it. That number isn’t a benchmark I read — it’s what we measured when we finally logged the work, and it sits deliberately above the 15-20% that most published guidance recommends and below the 30-50% that teams actually report burning. The gap between those two ranges is the whole problem: the recommendation describes a healthy suite, and you don’t have one yet.
Do the arithmetic before you ask for the money
You can model most of this from two inputs: how many red builds per sprint turn out to be flake, and how long a human spends deciding that. Slack published the second number — 28 minutes per manual triage across their mobile CI. Here’s the same math on our suite, for one two-week sprint:
| Line item | Volume | Minutes each | Hours |
|---|---|---|---|
| Flaky red builds triaged | 60 | 28 | 28 |
| Tests actually repaired | 18 | 90 | 27 |
| Re-runs, PR unblocking, “is checkout broken?” | — | — | 12 |
| Total | 67 | ||
| Team capacity (5 SDETs × 64 productive hours) | 320 | ||
| Maintenance share | 21% |
The formula says 21%. Our six-week log said 31%. That gap is the context switching the model can’t see — the third time in a day you stop writing a new test to explain that no, the checkout suite isn’t broken, it’s the shared staging environment again. Ask for 30%, and defend it with your log, not my table.
Label six weeks of work, don't estimate it
Every hour spent on a test that already exists gets a label — triage, repair, data, environment. No new tooling. A Jira label and a rule that nobody logs it anywhere else.
Stop letting retries hide the bill
If retries: 2 is quietly turning flakes into green builds, you have no data — and you’ve also destroyed the urgency that was going to fund the fix. Playwright’s failOnFlakyTests (1.52+) puts them back on the board.
Present it as an invoice, not a request
“We already spend 31% of QA capacity here. It is currently billed to the coverage budget, which is why coverage is late.” You are not asking for time. You are showing what the org already bought.
import { defineConfig } from '@playwright/test';
export default defineConfig({ retries: process.env.CI ? 2 : 0, // 1.52+: a test that only passed on the retry now fails the run. // You cannot budget for a cost your config is hiding from you. failOnFlakyTests: !!process.env.CI,});”We’re spending 30% of QA on tests that already exist?”
Yes — and a leader who finds that alarming is right. A 30% flake load is not a thing to fund forever; it’s a symptom, and the honest response is partly to kill the cause rather than permanently subsidize the treatment. Any QA lead who wins this argument and then defends the 30% line for three years has stopped being useful.
The 30-40% figure that gets quoted as an industry constant is not physics, either. Google runs at roughly 1.5% flaky test runs, and I’ve seen a 1,500-test suite held under 1% by a team that simply owned its own data-testid attributes. The 30% is a bill for decisions made upstream of you — locators you don’t control, environments you don’t own, test data nobody maintains. Fund it, and then go spend it on the upstream.
The exit condition that makes it a budget instead of a subsidy
Ours: when the flake rate stays under 2% of executed tests for two consecutive sprints, the carve-out drops by 10 points at the next planning cycle. That single sentence is what turned a “no” into a “fine, show me in a quarter” — because it made the 30% a claim I could be held to, rather than a permanent ask.
61% → 89%
Sprint commitments hit
9.4% → 2.1%
Flake rate (2 quarters)
30% → 15%
Carve-out by Q4
22 → 24
New tests per sprint
That last number is the honest one, and it’s the one I’d lead with if I ran the meeting again. New-test output went up by two. It couldn’t have gone much further either way — we had been spending that 30% all along, just without permission. The budget didn’t cost the org new coverage. It made the coverage forecast true for the first time.
The uncomfortable finding came out of the triage log: roughly 40% of what we’d been calling “flaky” was not a test defect at all. It was product race conditions and environment drift. That’s the argument’s real payoff — a test that fails intermittently and passes on retry is usually telling you something, and an unfunded team never has the hours to listen. They suppress instead, which is how you end up with a green suite that’s hiding real bugs.
What does the budget buy that a quarantine policy alone can’t?
Enforcement. Every quarantine policy has a fix-or-delete SLA in it, and every one of them fails the same way — not because the rule was wrong, but because nobody was given the hours to satisfy it. An SLA is a promise about capacity. If the capacity isn’t on the board, the SLA is decoration.
I’ve watched that happen, and written up what six months of an unfunded quarantine policy actually cost. The short version: a skip list is the only thing in a test suite that grows without anyone deciding to grow it. That team wrote the policy and skipped the budget, which is the same thing as writing no policy at all. This is also the structural answer to the accountability gap shift-left left behind — QA absorbing maintenance for breakage it didn’t cause, and calling it a work ethic.
Start with the log, not the ask
Don’t walk into next planning and ask for 30%. You’ll lose, the same way I did, to the sentence “the tests are already written” — because right now you have an opinion and they have a roadmap.
Go label six weeks of maintenance hours instead. Then walk in with your own number, whatever it turns out to be, and the exit condition attached to it. The argument stops being about whether maintenance deserves capacity and becomes about whether the invoice you’re holding is accurate. That’s an argument you win, because you’re the only person in the room who did the measurement.
What percentage of QA capacity should go to test maintenance?
Start at 30% of QA capacity if you have never measured it, then lower it as the flake rate falls. Published guidance clusters at 15-20%, but teams that actually log the work report 30-50%. Measure your own number over six weeks before committing to one — the difference between those ranges is the difference between a healthy suite and yours.
Is 30% of sprint capacity too much to spend on flaky tests?
It’s too much to spend forever, which is why the budget needs a published exit condition. Tie the carve-out to a flake-rate target — ours dropped by 10 points once flake stayed under 2% of executed tests for two consecutive sprints — so the line burns down instead of becoming permanent. A maintenance budget with no exit is just a subsidy with a spreadsheet.
How do I justify a test maintenance budget to leadership?
Reframe it from a request into an invoice. Log every hour spent on tests that already exist for six weeks, then show that the org is already paying that cost — out of the coverage budget, which is why coverage keeps slipping. You aren’t asking for new capacity. You’re asking for a cost you already pay to become visible, and for the velocity blame to move off your team.
Does budgeting for maintenance reduce new test coverage?
In our case it didn’t. New tests per sprint went from 22 to 24 after we carved out 30%, because the team had been spending that time all along without permission. What actually changed was predictability — sprint commitments hit went from 61% to 89%, and the coverage forecast became something you could plan against.
Do quarantine policies remove the need for a maintenance budget?
No — they depend on it. A fix-or-delete SLA is a promise about capacity, so without funded hours the skip list only grows. I’ve written up what six months of an unfunded quarantine policy actually costs. The policy was fine. The budget was missing.
