QA is the easiest line item to cut. It has no visible output, it delays the launch date, and skipping it appears to cost nothing right up until the moment it costs a great deal.
This is the arithmetic behind why that trade almost never works out, and what to do if you are currently shipping with no automated tests at all.
The multiplier that drives everything
A defect gets roughly an order of magnitude more expensive at each stage it survives. The exact factor varies by study and by organisation; the shape is consistent everywhere it has been measured.
- Caught while writing the code: minutes. The developer has full context and fixes it before anyone else sees it.
- Caught in code review: under an hour. Two people are now involved, and the author has to reload the context.
- Caught in QA: hours. Write the report, reproduce, fix, re-verify, re-deploy.
- Caught in staging by a stakeholder: a day or more, and it now involves a conversation about the release date.
- Caught in production by a customer: days, plus support time, plus a hotfix release, plus the customers who hit it and said nothing.
The reason is not that the fix itself gets harder. It is that the number of people involved, the amount of context that must be rebuilt, and the coordination overhead all grow at each step.
The four costs that never appear in the estimate
Support load
Every production bug generates tickets. Each ticket costs staff time to triage, reproduce, and respond to — and that cost repeats for every affected customer, not once for the bug.
Trust, which does not recover linearly
Users forgive a bug. They do not forgive a pattern. Once a product is perceived as unreliable, adoption of new features slows, feedback dries up, and churn rises for reasons customers do not always articulate. This cost is invisible in any dashboard and dwarfs the others.
Roadmap tax
A team firefighting production issues is not building. Two or three serious incidents a month can consume a meaningful fraction of a small team's capacity, and it is the unplanned, unpredictable fraction — which makes every future estimate less reliable.
Context switching
An urgent production bug does not cost only the time to fix it. It costs the interrupted work, the lost mental context, and the ramp back in. For a developer mid-feature, a "quick" thirty-minute fix routinely costs half a day of real output.
Ask what a two-hour outage on your busiest day would cost in revenue and support time. Compare it to a month of testing. The comparison is usually not close.
What to automate, and what genuinely is not worth it
The goal is not maximum coverage. It is the highest confidence per hour of maintenance. In practice:
Automate: the paths where failure costs money
Sign-up and login. Checkout and payment. Subscription changes. Anything writing to a permanent record. Anything a customer sees within thirty seconds of arriving. These are few in number and high in value — get them covered before anything else.
Automate: business logic with real rules
Pricing calculations, tax, discounts, permission checks, date handling, state machines. Fast unit tests, no infrastructure needed, and they catch the class of bug that is hardest to spot by reading code.
Automate: everything that has broken before
Every production bug should leave behind a test that would have caught it. This single rule builds a suite that is precisely shaped to your product's actual weaknesses, at close to zero incremental cost.
Do not automate: rapidly changing UI details
Tests asserting exact pixel positions or copy that changes weekly break constantly, teach the team to ignore failures, and cost more than they return. Test behaviour and outcomes, not layout.
Do not automate: subjective judgement
Whether a flow feels confusing, whether the tone is right, whether an animation is pleasant — these need a human. Manual testing is not the primitive version of automated testing; it answers different questions.
Starting from zero, in the right order
If you have no tests today, do not attempt comprehensive coverage. Do this instead:
- Write down the money path. The five to ten steps where failure directly costs revenue or trust. Usually: register, log in, find a product, purchase, receive confirmation.
- Automate a smoke suite for exactly those steps. End to end, running against a real environment, finishing in under ten minutes.
- Run it on every deploy, and block on failure. A suite that can be ignored will be ignored.
- Add a unit test for every bug you fix, forever. No exceptions, including for trivial bugs.
- Add unit tests to the ten most complex functions in the codebase. Whoever has been on the team longest knows exactly which ones they are.
That is typically two to three weeks of work and eliminates most catastrophic regressions. Broader coverage can grow from there at a comfortable pace.
Two kinds of testing that get skipped entirely
Performance under realistic load
An application that is fast with 50 records and three users can be unusable with 50,000 records and three hundred. Test with production-scale data before your customers do it for you — this is where N+1 queries, missing indexes, and unbounded pagination reveal themselves.
Security as part of QA
Access control in particular belongs in the automated suite: log in as user A, request user B's resource, assert a rejection. This one class of test catches the most common serious vulnerability in business applications and costs almost nothing to write.
Making the suite outlive the people who wrote it
A test suite nobody trusts is worse than no suite, because it consumes time and provides false comfort. Three things keep it alive:
- Fix flaky tests immediately or delete them. A test that fails randomly trains the team to ignore red builds, which disables the entire mechanism.
- Keep it fast. A suite taking forty minutes gets skipped under pressure. Ten minutes gets run.
- Make failures self-explanatory. A failure message should identify what broke without requiring the reader to understand the test's internals.
If an external team builds your tests, insist that the suite runs in your CI, that your developers can run it locally in one command, and that it is documented well enough to extend. A test suite you cannot maintain is a deliverable that expires.
That handover is deliberately part of our QA & Test Automation service — the point is a suite your team keeps running long after the engagement ends, not a report that impresses once.
