The Bottleneck Moved
Picture a Series B SaaS company with about forty engineers across six teams. Nothing exotic — a multi-tenant web application, a handful of backend services, a Postgres cluster, a React frontend, a mobile app that lags a version behind, and the usual constellation of third-party integrations for payments, email, analytics, and identity.
Twelve months ago the company rolled out AI coding assistants and, later, coding agents. Within two quarters, engineers were routinely generating implementations from a ticket description, refactoring services they had never opened, producing migrations, scaffolding API endpoints, rewriting frontend components, generating test fixtures, and opening pull requests at a rate nobody had planned for. Onboarding got faster. The "nobody has time for this" backlog started to move. Engineers who had avoided the billing service for two years began touching it.
By any conventional measure of engineering activity, the company got faster. Commits up. Pull requests up. Files touched up. Time-from-ticket-to-first-draft down sharply.
Then the second-order effects arrived.
The pull request queue stopped clearing. Reviewers who used to turn around a diff over coffee now faced four-hundred-line changes spanning six files and two services, and started leaving them for tomorrow. CI runtimes crept from eleven minutes to twenty-six as teams added tests to compensate for their own uncertainty. QA began receiving three or four features at once, late in the sprint, each with a blast radius nobody could describe confidently. Staging developed a permanent queue. Release candidates went back for a second and third pass. And the number of changes bundled into each release grew, because breaking them apart had become operationally expensive.
Nobody did anything wrong. The engineers were not sloppy. The QA team was not slow. The AI tools worked more or less as advertised.
What happened is that one part of the system got dramatically faster while the rest of it did not.
The bottleneck did not disappear. It moved.
For most of software history, the flow looked roughly like this:
Idea → Engineering capacity → Testing → Release
^ the constraint
Adding engineering capacity increased throughput, because engineering capacity was the binding constraint. Every process improvement of the last twenty years — frameworks, cloud infrastructure, CI/CD, open source, DevOps, infrastructure as code, platform engineering, better IDEs, and now generative AI — attacked that same constraint from a different angle.
With AI-assisted and agent-assisted development, the flow in many organizations increasingly looks like this:
Idea → Rapid change generation → Verification queue → Release
^ the constraint
This is not a hypothetical shape. CircleCI's 2026 State of Software Delivery report, based on more than 28 million CI workflows, found that average workflow throughput across all teams grew 59% year over year — the largest jump in the report's seven-year history. But for the median team, feature branch throughput increased 15% while main branch throughput fell 7%. Activity climbed where teams build. It declined where teams ship. Main branch success rates dropped to about 70%, the lowest in over five years, meaning nearly three in ten attempts to merge to production were failing, and median recovery time rose 13% year over year to 72 minutes.
CircleCI's own framing is worth sitting with: a factory that can produce more components than it can assemble does not become more productive. It accumulates inventory.
The question this article is built around is therefore not "how fast can your team write code?" It is:
How much change can your organization actually verify — not merely produce?
That question has a different answer at every company, and for most of them nobody has ever measured it. It has never needed measuring, because code production was always the slower step.
[Visual concept: A two-panel flow diagram. Panel A, "Before": a wide pipe labeled "idea" narrowing sharply at "engineering capacity," then widening through testing to release. Panel B, "Now": the engineering constriction widened dramatically, with the narrow point relocated to a stage labeled "verification & release decision," and a visible backlog of change units queued in front of it.]
Part I — The Velocity Inversion
The industry has spent two decades systematically attacking the cost of writing and changing code. Reusable frameworks removed boilerplate. Cloud infrastructure removed procurement. CI/CD removed manual release choreography. Open source removed the need to build commodity components. Infrastructure as code made environments reproducible. Platform engineering turned undifferentiated setup work into a paved road. Every one of these was a compounding win, and every one of them targeted the same constraint.
AI is the latest step in that sequence, but it is a step of a different size, because it reduces the marginal effort of producing a plausible change to near zero — not just the boilerplate around the change, but the change itself.
That distinction matters. A framework reduces the cost of the tenth similar endpoint. An AI agent reduces the cost of the first attempt at an unfamiliar one.
The scale of this shift is now visible in public data. Google's CEO stated in April 2026 that 75% of all new code at Google is AI-generated and approved by engineers, up from 50% the previous fall, describing a move toward agentic workflows where engineers orchestrate autonomous digital task forces. DORA's 2025 State of AI-assisted Software Development report, drawing on nearly 5,000 survey responses and more than 100 hours of qualitative data, found 90% of respondents using AI in their daily software development work. LinearB's 2026 benchmark analysis of 8.1 million pull requests across 4,800 teams in 42 countries found 88.3% of developers now using AI regularly, up from just under 72% in early 2024.
Why "lines of code" is the wrong lens
There is a persistent temptation to measure this shift in volume — lines written, commits made, files generated. That framing is misleading in both directions, and engineering leaders should resist it explicitly.
Volume is a poor proxy for value because a change's cost is not its size — it is the work required to understand, review, verify, deploy, and support it. A one-line change to a payment webhook can carry more risk than a two-thousand-line isolated report. But volume also understates what changed, because AI increases far more than characters produced. It increases:
- the number of proposed changes entering review;
- the number of files and modules touched per change;
- the frequency of refactoring, including refactoring of code the author does not know well;
- the rate of speculative work — alternative implementations, spike branches, experiments that may never merge;
- the breadth of parallel development, since one engineer can now supervise several concurrent workstreams;
- the rate of dependency and configuration changes;
- the volume of generated tests, which are themselves artifacts requiring maintenance;
- the speed of bug fixes, including fixes applied under time pressure to code nobody has read carefully.
Every one of those is a real productivity gain at the point of creation. And every one of them creates a verification obligation downstream.
The LinearB data makes the shape of that obligation concrete. At the 75th percentile, AI-assisted pull requests contained over 400 lines of code compared to 157 for unassisted work, with agentic pull requests in the middle at roughly 290 lines. LinearB notes that it has long recommended keeping pull requests below 300 lines because that represents a manageable chunk of information humans can hold in working memory — a threshold AI-assisted work routinely exceeds.
More striking is what the same dataset found about the character of AI-generated change. Measuring refactor rate — the share of a pull request that modifies existing code paths rather than adding new ones — unassisted pull requests showed approximately 37% refactoring at the 75th percentile, while AI-assisted pull requests showed nearly zero. LinearB's interpretation is that AI is almost exclusively generating new code, expanding codebases with new implementations that may duplicate functionality, ignore established internal libraries, or bypass architectural patterns the team standardized on.
GitClear's longitudinal analysis points the same direction from a different dataset. Tracking code-change signals across 2023–2026, GitClear reports that block duplication climbed from 40.3 per million changed lines in 2023 to 73.0 year-to-date in 2026, an 81% increase and the highest level on record, while the percentage of moved (refactored) code fell from 21% in 2022 to 13% in 2023 and then to 3.8%. GitClear frames duplication as a propagation tax: when a developer changes one copy of a duplicated block, they inherit the obligation to find and evaluate every sibling — across files and domains they may not know — and decide whether the change must propagate. Related reporting on the same research notes that legacy refactoring — changes that remove or update code last touched more than 12 months ago — has fallen 74% since 2023, and functional connectivity, a measure of how often new commits call existing functions, has fallen by 35%.
Read carefully, none of that says AI-generated code is bad. It says AI-generated change has a different shape: larger, newer, more additive, less connected to what already exists. And a change's shape determines how much verification it demands.
Two production systems, one accelerated
Here is the framing that anchors the rest of this article. Every software organization runs two production systems in parallel:
- A system that creates changes. Engineers, tools, IDEs, agents, repositories, branches.
- A system that creates justified confidence in those changes. Reviews, automated tests, environments, pipelines, exploratory investigation, security validation, performance checks, observability, staged release mechanisms, and the human judgment that turns all of that into a decision.
AI has strongly accelerated the first system. In most organizations, the second system is running on infrastructure and process designed for the volume and shape of change from two or three years ago.
That gap — between change creation rate and confidence creation rate — is where the new bottleneck lives.
Be precise about a claim this article does not make. The argument does not require that AI-generated code is buggier or less secure than human-written code. Suppose generated changes were statistically identical in defect density. Doubling the number of changes entering a verification system of fixed capacity would still double demand, lengthen queues, increase the number of unverified changes per release, and raise the probability that something reaches production without adequate scrutiny.
Output-quality questions are real, and Part III returns to them including the security evidence. But they are a second problem layered on a first one that is purely throughput mismatch. Leaders who fix only the former will not recover their delivery velocity.
Part II — The Invisible Verification Queue
Most engineering organizations can tell you their sprint capacity, their headcount plan, and their cloud spend. Very few can tell you their verification capacity.
Here is a working definition, offered as a management concept rather than a formal standard:
Verification capacity is the rate at which an organization can evaluate software changes deeply enough to make a responsible release decision about them.
Note what that definition does and does not include. It is not "how many test cases can we run." It is not "how many QA engineers do we employ." It is the rate at which change becomes decidable — the point at which someone with accountability can say, with reasons, that this change is safe enough to put in front of customers.
That capacity is assembled from many components, and each of them has its own ceiling:
- automated functional and unit testing;
- integration and API testing;
- contract testing across service boundaries;
- regression testing, whether targeted or full-suite;
- security validation, from static analysis to dependency scanning to manual review of sensitive paths;
- performance and load testing;
- compatibility testing across browsers, devices, and API versions;
- data validation, including migration correctness at production scale;
- exploratory testing by humans;
- code review and design review;
- observability sufficient to detect problems that pre-production testing missed;
- production monitoring and alerting;
- release safeguards — flags, canaries, staged rollouts, rollback paths.
Why "just add more tests" does not create unlimited capacity
The intuitive response to a verification shortfall is to write more tests. That helps, and often it helps a great deal. But tests are not free capacity. They are themselves assets with carrying costs.
Every automated test consumes execution time, infrastructure, and money on every run. It consumes maintenance effort each time the code it touches changes. It consumes debugging effort when it fails. It consumes analysis effort when someone has to decide whether a failure is real. It consumes environment capacity if it needs a database, a browser, or a dependency. And it consumes the scarcest resource of all: engineering attention.
A team that doubles its test suite has not necessarily doubled its verification capacity. If suite runtime doubles from twenty to forty minutes and the number of pull requests also doubles, the queue in front of CI grows superlinearly, feedback slows, engineers start batching changes to avoid the wait, and batching increases the blast radius of every merge. The suite got bigger. The organization's ability to clear change got worse.
This is the part that surprises founders. Verification is a system, and systems have queues, and queues behave in ways that are not intuitive.
The Verification Pressure Ratio
To reason about this without turning it into a mathematics exercise, it helps to have a shared heuristic. The following is an illustrative management concept proposed for this article, not an established industry standard or a metric with a defined calculation method. Its value is in the conversation it enables, not in the number it produces.
Verification Pressure Ratio (VPR) = the rate of meaningful change entering verification ÷ the rate at which the organization can confidently clear those changes.
"Meaningful change" means a change that requires a real decision — not a typo fix, but anything that touches behavior, data, contracts, configuration, or dependencies. "Confidently clear" means reaching a state where someone would defend the release decision afterward.
The ratio cannot be computed precisely, and any attempt to do so will produce false confidence. What it gives you is a way to describe three qualitatively different regimes:
Comfortably below 1. Verification has spare capacity. Changes are picked up quickly. Reviewers have time to think. Test failures get investigated the day they appear. There is slack to absorb an incident, a holiday, or a surprise. The organization can raise development throughput without redesigning anything.
Around 1. The system is at equilibrium and therefore fragile. It works on a normal week and falls behind whenever anything is abnormal — a flaky test cluster, a staging outage, two people on vacation, an unusually large feature. Recovery is slow because there is no spare capacity to catch up with. Most teams that describe QA as "fine, but tight" are living here.
Persistently above 1. Work accumulates. This is the state that produces the symptom list every engineering leader recognizes:
- QA queues that grow rather than clear;
- release cycles that lengthen even though development got faster;
- testing that becomes broader but shallower;
- regression coverage deferred to "next release";
- reruns used as a substitute for investigation;
- environments in permanent contention;
- sign-offs made under time pressure rather than on evidence;
- performance, accessibility, and security checks skipped first, because they are easiest to postpone;
- large batches of changes released together, because splitting them costs more than shipping them;
- production incidents that surface issues pre-production testing was supposed to catch.
The queueing logic explains why the deterioration is not gradual. As a processing system approaches full utilization, waiting time rises sharply rather than linearly, and becomes increasingly sensitive to variability. A verification system at 70% utilization absorbs a bad week; the same system at 95% turns a bad week into a two-sprint backlog. It is the dynamic that makes a highway at 95% capacity produce stop-and-go traffic while the same road at 70% flows freely. Adding AI to code production is, in these terms, widening the on-ramp without touching the highway.
[Visual concept: Two overlaid rate curves over time — "meaningful changes arriving" rising steeply after an AI adoption marker, and "changes cleared with confidence" rising only slightly. The growing area between them is shaded and labeled "accumulated unverified change." A second small panel shows waiting time as a function of utilization, flat until roughly 70% and then bending sharply upward.]
What the queue looks like in real data
The verification queue is usually invisible because no single dashboard shows it — it is distributed across review tools, CI systems, environment schedules, and test management systems, each owned by a different group. But its fingerprints show up in aggregate data. LinearB's 2026 benchmarks found that AI-generated pull requests wait more than 16 hours on average before a reviewer picks them up, compared to approximately 200 minutes for unassisted work. The report attributes this hesitation to reviewer uncertainty about the mental load required, concerns about errors or missing context, and ambiguity about ownership that reduces the social motivation to help a colleague ship their work.
The second half of that finding is the more uncomfortable one. Once review begins, AI-generated pull requests move through the review cycle faster — roughly 194 minutes compared to 252 for manual work — and LinearB is explicit that this should not be interpreted as a positive signal, as it likely reflects superficial validation rather than thorough scrutiny.
That is what a saturated verification system looks like from the inside: work waits longer, then gets processed faster. Not because it became easier, but because the depth of processing quietly dropped to match the available capacity. Nobody decides to do this. It is what a queue does to the people standing in it.
The end-to-end consequence in the same dataset: unassisted pull requests merged at approximately 84.5% within 30 days, while AI-generated pull requests merged at just 32.7%. Several explanations are plausible — abandoned speculative work, code that misses standards, changes that solve the wrong problem, or simple lack of capacity to evaluate them — and the report lists all of them rather than picking one. But the systems-level reading is hard to avoid: a large share of generated code is not converting into delivered value.
Here is a compact way to hold the whole pattern:
| What AI changes about development | The verification consequence |
|---|---|
| More changes proposed per engineer per week | More items entering review, CI, and test queues; arrival rate rises against fixed clearance rate |
| Larger changes per pull request | Higher reviewer cognitive load per item; harder to reason about blast radius; slower and shallower review |
| More additive code, less refactoring of existing code | Codebase surface area grows; duplication creates propagation obligations across unfamiliar files |
| Changes made in unfamiliar parts of the codebase | The author's intuition about risk — historically a key filter — is weaker or absent |
| More parallel workstreams per engineer | More concurrent branches competing for shared environments and test infrastructure |
| More generated tests | Larger suites, longer CI, more maintenance surface, more opportunities for flakiness |
| Faster fixes under time pressure | More small high-risk changes that skip deep review because they look trivial |
| More speculative and experimental branches | Verification effort spent on work that may never merge |
Every row in that table is a good thing on the left and a cost on the right. That is precisely why the problem is hard to see: the benefits are visible and immediate, and the costs are diffuse, delayed, and spread across other people's teams.
[Internal link opportunity: Quality Engineering strategy]
Part III — Why AI-Generated Change Expands the Regression Surface
If you asked most engineering leaders to estimate the risk of a change, they would start with its size. Small diff, small risk. Large diff, large risk.
That heuristic has always been imperfect, and AI-assisted development makes it substantially worse.
Software is not a pile of lines. It is a network of dependencies, contracts, assumptions, and shared state. A change's risk is a function of its position in that network, not its length. Modifying three lines in a shared authorization helper can affect every endpoint in the system. Adding four hundred lines of a self-contained CSV export touches nothing.
Call the set of behaviors that a given change could plausibly affect its regression surface. This is a conceptual term, not a metric with a standardized definition — you cannot compute it exactly, and anyone who claims to has oversimplified. But it is a far more useful mental model than diff size, and it is the thing risk-based verification is actually trying to estimate.
A single modification can propagate into:
- API contracts — request and response shapes, status codes, error semantics, nullability, ordering guarantees;
- database behavior — query plans, index usage, lock contention, transaction boundaries, constraint interactions;
- caching layers — key construction, invalidation timing, stale-read windows, cache stampede behavior;
- state machines — which transitions are legal, what happens on retry, what happens on partial failure;
- asynchronous jobs — queue semantics, ordering, at-least-once versus exactly-once delivery, dead-letter handling;
- permissions and authorization — role checks, tenant isolation, resource ownership, delegated access;
- frontend assumptions — implicit contracts about field presence, response timing, error shapes, routing behavior;
- downstream services — anything consuming an event, an API, or a database view;
- third-party integrations — webhook payloads, idempotency keys, rate limits, signature verification;
- reporting and analytics — event schemas, aggregation logic, historical comparability;
- notification systems — triggering conditions, deduplication, delivery timing.
The familiarity paradox
Historically, engineers estimated regression surface using something they rarely articulated: familiarity. An engineer who had worked in the billing service for two years knew, without consulting anything, that the invoice generator was also used by the dunning job, that the tax calculation had a special case for one enterprise customer, and that the retry logic there was not idempotent. That knowledge was the risk model.
AI coding tools are extraordinarily good at letting engineers work productively in code they do not know. That is one of their most valuable properties — it dissolves knowledge silos and lets small teams maintain larger systems. It also removes the filter. The engineer who previously could not touch the billing service was, in effect, prevented from introducing unassessed risk there. Now the change takes twenty minutes, and the informal assessment that used to accompany it — "careful, this also runs in the dunning job" — has no obvious replacement.
This is the paradox at the center of AI-assisted development: the tool that lets engineers work across unfamiliar code removes the mechanism engineers historically used to estimate the risk of working in unfamiliar code.
Nothing about this implies the change is wrong. It implies the change arrives without its risk metadata attached, and the verification system now has to supply what the author's memory used to supply.
Local correctness versus system correctness
Generated code frequently exhibits a specific and difficult property: it is locally correct and systemically wrong.
It compiles. It satisfies the type checker. It passes the unit tests. It implements the interface that was requested. Read in isolation, it looks like code a competent engineer would write, because in a meaningful sense it is.
System behavior, however, is not the sum of locally correct parts. It emerges from interactions — with data that exists, with clients that already made assumptions, with jobs that run at 3 a.m., with the specific way this organization uses a general-purpose library.
The Stack Overflow 2025 Developer Survey, with over 49,000 respondents from 177 countries, captured this pattern from the practitioner side: 66% of developers reported frustration with AI solutions that are "almost right but not quite," often spending more time debugging AI-generated code than writing it themselves, while 46% said they no longer trust the accuracy of AI outputs, up from 31% in 2024. "Almost right but not quite" is a precise description of local correctness without system correctness.
Six illustrative failure patterns follow. These are constructed examples chosen to show categories of blast radius, not war stories, and none of them is dramatic. That is deliberate. Catastrophic failures get caught. It is the plausible ones that ship.
1. A query optimization that changes semantics under NULLs. A generated change rewrites a reporting query, replacing a correlated subquery with a LEFT JOIN plus a WHERE filter. It is faster and returns identical results against the seeded test dataset. In production, the filter on the joined table converts the outer join into an effective inner join wherever the joined column is NULL, and a segment of records silently disappears from a monthly report. Nothing errors; the number is just wrong until a customer notices in week three. Regression surface: reporting, analytics, any downstream consumer of that aggregate.
2. An API refactor that preserves the happy path and breaks the error contract. A service's validation logic is cleaned up and successful responses are byte-identical. But failures that previously returned 422 with an {"errors": [...]} array now return 400 with {"detail": "..."}. The consumer's tests mock the success case only, so nothing fails in CI. In production the consumer's error handler falls through to a generic branch, and a class of user-facing validation message becomes "Something went wrong." Regression surface: every consumer of that endpoint, including mobile clients on older versions.
3. A retry wrapper applied to a non-idempotent operation. Asked to improve resilience around a flaky third-party call, an agent adds exponential-backoff retries — correct in principle. But the wrapped operation posts a charge, and the idempotency key was being generated inside the wrapped function rather than passed in. A timeout that produced one failed charge now produces two successful ones. No test using a mocked payment provider will see this. Regression surface: financial correctness, reconciliation, support load.
4. A frontend refactor that passes component tests and breaks history. A route-level component is restructured to use a state-based tab switcher instead of nested routes. All component tests pass — they render and assert on the DOM. What no test covers is that the browser back button now exits the page instead of returning to the previous tab, and that customer-shared deep links no longer resolve. Regression surface: navigation, shared links, bookmarks, analytics attribution.
5. An authorization change that checks the role and forgets the owner. A permissions refactor correctly verifies that the requesting user holds the manager role before allowing access to an employee record. It does not verify that the employee belongs to the requesting user's organization. Every test passes, because every test fixture has one organization. Regression surface: tenant isolation, data privacy, regulatory exposure. This class of bug is rarely found by functional testing and is one of the strongest arguments for treating authorization as a distinct verification concern.
6. A migration that works on clean data and stalls on real data. A generated migration adds a NOT NULL column with a default and backfills in a single statement. On the 4,000-row test database it finishes in under a second. On the 90-million-row production table it takes a lock and holds it. The migration is correct; its operational behavior at production scale is not. Regression surface: availability — a verification gap about data volume and shape, not logic.
None of these requires AI to have made a mistake in any conventional sense. Several of them are changes a competent engineer might make. What has changed is the rate at which such changes are proposed, and the fact that fewer of them arrive with an author who could have said "wait — check the dunning job."
[Visual concept: A blast radius diagram. A single small code change at the center, with concentric rings expanding outward through direct callers, service boundaries, async consumers, data stores, third-party integrations, and analytics. Two changes of identical diff size are shown side by side — one with a tight radius, one whose radius crosses four boundaries — making the point that size and risk are different axes.]
Combinatorial interaction risk — stated carefully
There is a common claim that risk grows exponentially with change frequency. That claim is too strong and should not be made without qualification.
What can be said accurately is narrower and still important. When multiple changes land in the same release window, the system must be correct not only under each change individually but under their combination. Two changes each correct in isolation can interact badly: one adds a cache, another changes the write path that should invalidate it; one changes an event schema, another changes a consumer's assumption about ordering.
The number of pairs of changes in a release grows quadratically. In practice only a small fraction of those pairs can interact at all — most changes are genuinely independent — so real-world interaction risk grows far more slowly than the raw combinatorics suggest. But it does grow superlinearly with batch size, and fastest where changes cluster around shared components: shared libraries, authentication, the data layer, deployment configuration.
This gives a concrete, defensible reason for a practice that is often justified on vibes alone: batch size is a verification variable, not just a delivery preference. DORA's 2025 research found that working in small batches counteracts the risk of AI generating large, unstable changes, ensuring that speed translates to better product performance, and identified it as one of seven capabilities that amplify AI's benefits. When change arrival rate goes up and batch size goes up at the same time — which is exactly what the pull request size data shows — interaction risk rises on both axes simultaneously.
The security dimension, stated precisely
Security deserves separate treatment because the evidence here is more specific than the general "is AI code worse" question.
Veracode's 2025 GenAI Code Security Report evaluated 80 curated coding tasks across more than 100 large language models, structured so that each task could be implemented in either a secure or an insecure way. The finding: models chose the insecure option in 45 percent of cases, with Java showing a 72% security failure rate and cross-site scripting defenses failing in 86% of relevant samples. Veracode's spring 2026 update reported that while syntax pass rates climbed from about 50% to 95% since 2023, security pass rates remained essentially flat, hovering between 45% and 55% regardless of model generation or release date.
Read that carefully, because it is easy to over-claim. This benchmarks default behavior on security-relevant tasks without security-specific prompting. It is not a measurement of code real teams ship after review, static analysis, and their own secure-coding standards, and it does not establish that AI-generated code in production is 45% vulnerable.
What it does establish is more actionable: security correctness is not improving at the same rate as functional correctness. Models got dramatically better at producing code that works and not better at producing code that is safe by default. If your verification system treats functional tests passing as a proxy for acceptability, that proxy is degrading — not because the code got worse, but because the gap between "works" and "safe" is not closing.
The implication: security validation must be an explicit, independently-triggered part of the verification portfolio rather than a by-product of functional testing. This is where OWASP's application security guidance and the OWASP Top 10 for Large Language Model Applications belong — the latter for teams whose products themselves embed LLM features, which increasingly means most SaaS products.
[Internal link opportunity: software security testing]
Part IV — The Great Test Automation Misunderstanding
There is a comfortable answer to everything described so far, and it comes up in nearly every executive conversation on this topic:
"If AI generates more code, we'll just have AI generate more tests."
This is a reasonable instinct and it is partially correct. AI-assisted test generation is genuinely useful, and organizations that refuse to use it are leaving real capacity on the table. It is worth being specific about where it helps before discussing where it does not.
Where AI-assisted test generation earns its place. It produces initial coverage for the long tail of untested utilities and legacy modules nobody was ever going to reach. It builds scaffolding fast — fixtures, factories, setup and teardown, parameterized harnesses. It enumerates input variations, including boundary and malformed cases a human writing tests at 5 p.m. would skip. It turns written requirements into candidate test ideas, useful even when you discard half. It generates API tests from an OpenAPI specification with high fidelity, produces mocks and stubs, absorbs the repetitive mechanical work that consumes a disproportionate share of an automation engineer's week, and helps with maintenance — updating a hundred tests after a schema change, or explaining a two-day-old failure.
Those are real gains, and they are the reason Part XVII of this article argues for AI inside the verification system, not merely upstream of it.
But test generation solves a narrower problem than most executives assume, for a reason that is structural rather than a matter of model quality.
The shared-assumption problem
Testing provides value through independence. A test is useful because it encodes an expectation derived from a source other than the implementation. When the implementation drifts from the intended behavior, the independent expectation catches it.
Now consider the standard AI-assisted workflow:
Requirement → AI interpretation → Implementation
Requirement → same AI interpretation → Test
If the same interpretation of an ambiguous requirement drives both artifacts, the test does not check the implementation against the requirement. It checks the implementation against itself. The test passes. The code and the test agree. And they can agree while both being wrong about what the business actually needed.
A concrete version: a requirement says "users should be able to cancel their subscription at any time." The generated implementation cancels immediately and prorates a refund. The generated test asserts exactly that. Both are internally consistent. The business intent was cancellation at end of billing period with no refund — a distinction worth real money and one that no amount of test generation from the same prompt will surface.
This is not a flaw that better models fix, because it is not a modeling error. It is an epistemics problem: two artifacts derived from a single interpretation cannot validate that interpretation. Independence has to come from somewhere else — a human who understands the domain, a specification written before implementation, a contract owned by the consumer rather than the producer, a property that must hold regardless of implementation, or a test written by someone who did not write the code.
This is the strongest practical argument for keeping specification and acceptance criteria as first-class artifacts in an AI-heavy workflow, and for making sure that at least one link in the chain from requirement to release is grounded in something other than a model's reading of a ticket.
The failure modes of generated tests
Beyond the independence problem, generated test suites tend toward a recognizable set of weaknesses. None is unique to AI — human-written suites have all of them too — but generation produces them faster and in greater volume, and volume is exactly what makes them expensive.
Weak assertions. A test that calls an endpoint and asserts status == 200 has verified that the server did not crash. It has not verified that the response was correct. Generated tests skew toward assertions that are easy to write and unlikely to fail, because a test that fails on generation looks like a mistake.
Excessive mocking. When every dependency is mocked, the test verifies that the code calls the mocks in the expected order. It verifies nothing about whether the real dependency behaves that way. The payment retry example from Part III is invisible to a fully mocked test by construction.
Implementation coupling. Tests that assert on internal method calls, private state, or specific intermediate values break whenever the implementation is refactored — which, in an AI-assisted codebase, is often. These tests convert refactoring from a cheap operation into an expensive one, which is the opposite of what a test suite should do.
Happy-path bias. Generated tests reliably cover the path described in the prompt. They cover error paths, partial failures, concurrent access, and degraded dependencies far less reliably, because those paths are usually not described in the prompt.
Missing business invariants. The most valuable tests in most systems are not about individual functions. They are about properties that must hold across the whole system: an account balance never goes negative; the sum of line items equals the invoice total; a user cannot see another tenant's data; a cancelled order cannot ship. These invariants live in the domain, not in the code, and generation from code cannot recover them.
Duplicated logic, brittle selectors, and maintenance load. A test that reimplements the calculation it checks will agree with the implementation by construction, including when both are wrong. Generated UI locators tend toward whatever was in the DOM at generation time — nested CSS paths, index-based selection, text a copy change will break — which is a leading cause of the flakiness discussed in Part X. And every generated test is a permanent liability that must be updated, debugged, and eventually deleted. A suite growing faster than the team can maintain it does not increase confidence; past a certain point it decreases confidence, because engineers stop reading failures carefully.
The distinction that matters
Here is the compressed version, and it is worth repeating in leadership conversations:
Test generation scales test production. It does not automatically scale judgment.
Judgment decides what is worth verifying, what "correct" means for this business, which assertions would actually catch a real defect, and when the evidence is sufficient to release. Generation makes the mechanical part of testing cheap and leaves the expensive part exactly where it was.
An organization that answers a verification bottleneck by generating three times as many tests typically ends up with a slower pipeline, a larger maintenance surface, more flaky failures, and roughly the same justified confidence. The suite grew. The bottleneck did not move.
[Internal link opportunity: test automation]
Part V — From Test Coverage to Change Risk Coverage
The instinct behind most regression strategies is uniformity: every change goes through the same gate, the full suite runs on everything, and consistency is treated as fairness.
That instinct was affordable when changes were expensive to produce. It is not affordable when they are cheap.
Consider the arithmetic. If every pull request triggers a two-hour regression suite, doubling the number of pull requests does not double delivery throughput — it doubles load on a fixed-capacity resource. Parallelization gets you partway, as Part IX covers, but it does not address the deeper problem: most of that two-hour suite is irrelevant to most changes. Running it anyway is not caution. It is undirected effort consuming capacity you need for changes that actually warrant scrutiny.
The alternative is not "test less." It is to allocate verification depth in proportion to the risk being introduced. The objective shifts from test coverage — what percentage of code is exercised — to change risk coverage: for each meaningful change, has the organization done the verification appropriate to what could go wrong?
A Change Risk Classification model
What follows is an operational framework proposed for this article, not a formal or standardized testing model. Teams should adapt the dimensions to their own domain; a medical device company and a project management SaaS will weight these very differently.
Classify each change along dimensions such as:
- Customer impact — how many users and which ones? A change affecting one internal admin screen is not a change affecting checkout.
- Security exposure — does it touch authentication, authorization, secrets, input handling, or data access paths?
- Data integrity — can it corrupt, lose, or incorrectly transform stored data? Is the effect reversible?
- Architectural reach — how many services, modules, or teams does the change's regression surface cross?
- Transaction criticality — is money, contractual obligation, or regulated activity involved?
- Dependency depth — how many things consume the thing being changed? A shared library sits at the top of this axis.
- Reversibility — can it be rolled back cleanly in minutes? Data migrations and third-party state changes usually cannot.
- Observability — if this breaks in production, how quickly and reliably would you know? Poor observability raises the required pre-production verification depth.
- Novelty — is this a well-trodden pattern in this codebase, or the first time the team has done this kind of thing?
- Change size and locality — a weak signal on its own, but useful in combination with the others.
Note that several of these dimensions are properties of the system, not the change. Reversibility and observability are things you can invest in once and then benefit from on every subsequent change. That is a central theme of Parts VIII and XV: the cheapest way to increase verification capacity is often to make changes safer to make, rather than to test each one harder.
Mapping risk to verification depth
The table below maps example change categories to proportionate verification. It is illustrative — the point is the shape of the allocation, not the specific cells.
| Change category | Dominant risk dimensions | Proportionate verification |
|---|---|---|
| UI copy, styling, or content change | Low across all dimensions | Automated build and lint; visual regression check if one exists; peer review. No regression suite. Ship on merge. |
| Isolated backend calculation with no external callers | Novelty; low reach | Unit tests including boundary and error cases; property-based test if the function has invariants; targeted review of the business rule with someone who owns it. |
| New API endpoint, additive only | Reach; security exposure | Contract test published from the spec; API-level integration tests including auth and error responses; input validation and authorization tests; rate-limit behavior. |
| Change to an existing API response shape | Dependency depth; reach | Consumer-driven contract tests run against all known consumers; explicit compatibility check for older mobile clients; deprecation path; staged rollout with old and new shapes coexisting. |
| Authentication or session behavior | Security exposure; customer impact; reversibility | Dedicated auth test suite covering token lifecycle, expiry, refresh, and revocation; negative testing; security review by someone other than the author; staged rollout with elevated monitoring. |
| Authorization or tenancy rules | Security exposure; data integrity | Multi-tenant fixtures with at least two organizations and cross-org negative tests; resource-ownership assertions distinct from role assertions; manual security-focused exploration; audit logging verified. |
| Payment, billing, or subscription workflow | Transaction criticality; reversibility; customer impact | Full journey tests against provider sandbox; idempotency and duplicate-charge tests; failure and timeout injection; reconciliation check; exploratory session on edge cases; canary release with financial monitoring. |
| Database migration | Data integrity; reversibility; availability | Dry run against a production-shaped dataset (volume and distribution, not just schema); lock and duration analysis; explicit rollback or forward-fix plan; execution outside peak; backup verification beforehand. |
| Shared library or internal framework change | Dependency depth; architectural reach | Broad regression across all consuming services; contract tests at every boundary; staged adoption service by service rather than a single atomic upgrade. |
| Performance-sensitive path change | Customer impact; observability | Benchmark against a baseline with production-shaped data; load test at expected peak plus headroom; query plan review; latency monitoring with an explicit regression threshold. |
Two things stand out when you read this as a whole.
First, the top of the table is fast — genuinely fast, in minutes — and that is where a large fraction of an AI-accelerated team's changes actually live. Copy changes, small isolated additions, internal tooling. Treating those with the same ceremony as a payment change is where most organizations waste their verification capacity.
Second, the bottom of the table is not primarily about running more tests. It is about different kinds of evidence: production-shaped data, rehearsed rollback, staged exposure, monitoring thresholds, human investigation. You cannot get to release confidence on a database migration by running the functional suite more times.
Why this increases capacity without adding headcount
Risk-based allocation raises effective capacity through four mechanisms, none requiring hiring. It removes undirected work, returning the effort spent running irrelevant tests. It shortens feedback loops for most changes, which reduces batching and therefore interaction risk. It concentrates deep human attention on changes where judgment actually alters the outcome. And it makes risk explicit, so shipping a payment change with less scrutiny than usual becomes a visible decision rather than an accident of queue pressure.
The trade-off should be stated honestly: classification can be wrong. A change that looked like a copy change may turn out to touch a shared component. This is why classification should be assisted by tooling that inspects what the change actually touches — dependency graphs, call graphs, ownership metadata — rather than relying on the author's self-assessment, and why Part IX argues for periodic full-system validation regardless of what the classifier says.
The objective is not maximum testing. It is appropriate confidence for the risk being introduced.
[Internal link opportunity: regression testing]
Part VI — Why the Test Pyramid Alone Is Not Enough
The test pyramid is not wrong. Its core economic insight — that fast, cheap, isolated tests should vastly outnumber slow, expensive, integrated ones — remains correct and is arguably more important now that change volume is higher.
What the pyramid does not capture is that it organizes tests along a single axis: scope. Unit at the bottom, integration in the middle, end-to-end at the top. That was a sufficient model when the primary question was "how do we get adequate coverage at acceptable cost."
An AI-accelerated delivery system introduces axes the pyramid was never designed to represent:
- Change risk — the same suite is over-applied to some changes and under-applied to others, and the pyramid says nothing about which gets what.
- Service boundaries — in a distributed system the most valuable checks often live at boundaries rather than inside any one service's pyramid; contract tests have no natural home in the model.
- Observability and production validation — canaries, synthetic monitoring, and staged rollouts generate real evidence about real behavior, and fast production detection substitutes for some pre-production verification. Neither appears in the pyramid.
- Execution cost and confidence value — a fast test running on every commit is worth more than a thorough weekly one, and two tests at the same pyramid level can differ by an order of magnitude in risk retired per unit of maintenance.
- Failure containment — a flag limiting exposure to 2% of users changes the confidence threshold required to ship. That is a verification decision, and it happens after the pyramid ends.
The verification portfolio
A more useful frame for an AI-accelerated organization is a portfolio. Like a financial portfolio, it holds instruments with different costs, different speeds, different reliability, and different kinds of coverage — and its value comes from the combination, not from any single holding.
| Instrument | What it actually tells you | Speed / cost | Where it fails |
|---|---|---|---|
| Unit tests | Individual functions behave as specified in isolation | Seconds, near-free | Blind to integration, data shape, timing, and anything emergent |
| Contract tests | Two services agree on their interface, verified independently on both sides | Fast, moderate setup cost | Only covers what the contract encodes; nothing about semantics behind it |
| API / integration tests | Real requests produce correct responses against real dependencies | Minutes, moderate | Environment-dependent; a common source of flakiness |
| End-to-end tests | A critical user journey works through the whole stack | Slow, expensive, fragile | Poor at breadth; high maintenance; use sparingly and only on journeys that matter |
| Security tests (SAST, DAST, dependency scanning, authz tests) | Known vulnerability classes and access-control rules | Varies; mostly automatable | Blind to business-logic authorization flaws and novel patterns |
| Performance tests | Behavior under expected and peak load with realistic data | Slow, infrastructure-heavy | Only as good as the data shape and load model used |
| Exploratory testing | What you did not think to ask | Human time, high value per hour | Not repeatable; not a regression net; does not scale by adding hours |
| Feature flags | Limits who is exposed if you are wrong | Cheap once built | Adds configuration state and its own combinatorial surface |
| Canary / staged rollout | Real behavior under real traffic before full exposure | Requires deployment maturity | Needs enough traffic and good metrics to detect anything |
| Production telemetry and alerting | What is actually happening now | Ongoing investment | Only surfaces what you instrumented |
Release confidence is a property of the combination. A team with excellent unit tests, no contract tests, and no production telemetry has strong evidence about functions and weak evidence about the system. A team with mediocre unit tests, good canaries, fast rollback, and sharp alerting may ship more safely, because their evidence arrives from a different direction and their cost of being wrong is lower.
That last point is the one most worth internalizing: verification and containment are substitutes at the margin. Every dollar spent making failure cheap to detect and reverse reduces the amount of confidence you need before shipping. For a high-change environment, investment in containment often has a better return than investment in additional pre-production coverage.
The flow, end to end
CHANGE ARRIVES
|
┌─────────▼─────────┐
│ RISK CLASSIFICATION│ what does this touch?
│ (automated + human)│ what could it break?
└─────────┬─────────┘
|
┌─────────▼─────────┐
│ FAST DETERMINISTIC │ build, lint, types,
│ CHECKS │ unit, security scan
└─────────┬─────────┘ minutes — runs on everything
|
┌─────────▼─────────┐
│ INTEGRATION AND │ API tests, service
│ CONTRACT VALIDATION │ contracts, data checks
└─────────┬─────────┘ scoped to what changed
|
┌─────────▼─────────┐
│ TARGETED HIGH-RISK │ auth, payments, migrations,
│ TESTING │ performance, shared libs
└─────────┬─────────┘ only when risk warrants
|
┌─────────▼─────────┐
│ EXPLORATORY │ human investigation of
│ VALIDATION │ ambiguity and novelty
└─────────┬─────────┘ selectively, mission-driven
|
┌─────────▼─────────┐
│ RELEASE CONTROLS │ flags, canary, staged
│ │ rollout, rollback ready
└─────────┬─────────┘
|
┌─────────▼─────────┐
│ PRODUCTION EVIDENCE │ telemetry, synthetics,
│ │ error budgets, feedback
└─────────┬─────────┘
|
┌─────────▼─────────┐
│ BACK INTO RISK │ escaped defects reclassify
│ CLASSIFICATION │ future changes
└───────────────────┘
The loop at the bottom is the part most organizations skip. Every escaped defect is information about where the risk model was wrong. A verification system that does not feed production findings back into its classification will keep making the same allocation errors indefinitely.
[Visual concept: A funnel rather than a pyramid. Wide at the top where all changes enter, with the funnel splitting into lanes of differing depth based on risk classification — a short fast lane, a medium lane, and a deep lane. Below the funnel, a separate horizontal band labeled "containment" holds flags, canaries, and rollback, with an arrow showing that a wider containment band allows the lanes above it to be shorter.]
Part VII — Human Exploration Becomes More Valuable, Not Less
The second comfortable assumption is the mirror of the first: if AI can write code and tests, human testers become redundant.
The nuanced answer is that the composition of human testing work should shift substantially — and that the remaining portion becomes more valuable per hour, not less, precisely because change volume went up.
Start with what should move away from humans. Repetitive execution of predefined checks was never a good use of human attention, and in a high-change environment it is indefensible. If a person is manually clicking through the same regression script every release, that is capacity being burned on work a machine does better, faster, and more consistently. Automate it, and if it is not worth automating, question whether it is worth running.
What remains is investigation, and investigation is a different discipline.
Automated checks answer questions someone already thought to ask. They encode a hypothesis about how the system should behave and verify it repeatedly. That is enormously valuable and completely bounded: a test suite cannot fail in a way nobody anticipated.
Exploration does the opposite. A skilled tester with a live system, domain knowledge, and time forms new hypotheses as they go — noticing that a workflow behaves oddly when interrupted, that two features that were built separately now contradict each other, that an error message reveals internal state, that a screen reader cannot reach a control, that the sequence a real user would follow is not the sequence anyone tested.
Automation verifies what we know to ask. Exploration searches for what we failed to ask.
Where does human investigation retain disproportionate value?
Ambiguous requirements. When a specification permits two readings, a human notices and escalates; a generated test picks one and asserts it. Human review of behavior against intent is one of the few reliable ways to break the shared-assumption problem from Part IV.
Cross-feature interaction. Features are built by separate teams against separate tickets. Nobody's suite covers the new bulk-import feature combined with the existing approval workflow. Someone has to actually try it.
Business-logic inconsistency. A system can be functionally correct and commercially wrong — a discount that stacks in a way finance did not intend, a permission that is technically valid and organizationally absurd.
Unusual sequences and interruptions. Real users abandon flows, hit back, refresh mid-transaction, open two tabs, lose connectivity. Generated tests almost never do.
Accessibility and exploratory security thinking. Automated tooling catches some accessibility defects and misses the ones that matter most — whether the experience is genuinely usable with a keyboard or screen reader. Similarly, business-logic authorization flaws like the tenancy example in Part III are found by someone asking "what happens if I change this ID?" That instinct does not come from a scanner.
Product quality beyond correctness. Whether the thing is confusing, slow-feeling, or unpleasant is not a functional property, and it is invisible to every automated check you own.
Making exploration a system rather than a mood
Exploratory testing has a reputation for being unmanageable, which is mostly a consequence of doing it informally. Session-based or mission-driven exploration fixes that without turning it into scripted execution.
The structure is simple. A mission defines what is being investigated and why — "investigate whether tenant isolation holds across the new sharing feature," not "test the sharing feature." A timebox, typically 60 to 120 minutes, bounds the work. A charter notes what was covered, what was found, what was not reached, and what new questions emerged. The output is a set of findings and, importantly, a set of new hypotheses, some of which become automated tests.
This makes exploration schedulable, reviewable, and allocatable by risk. It also makes it visible in capacity planning, which matters when you are trying to answer the question in Part XIII about where your constraint actually sits.
Where should exploration not be used? Not as a regression net — it is not repeatable and does not scale by adding hours. Not against a stable specification that automation covers cheaply. And never as a substitute for missing automated coverage, which is the common expensive anti-pattern: teams re-checking the same things by hand every release consume exactly the capacity that should go into investigation.
The complementary relationship is the point. Automation holds the known ground so humans can go looking for the unknown. Where change volume has doubled and change familiarity has dropped, the unknown ground per release has grown. That is an argument for more investigation capacity, not less.
[Internal link opportunity: QA outsourcing]
Part VIII — The QA Bottleneck Is Often an Architecture Bottleneck
This is the section most worth a CTO's attention, because it reframes a problem that usually gets assigned to the wrong owner.
When releases slow, the conversation lands on QA: too small, too slow, too thorough, insufficiently automated. Sometimes that is accurate. Frequently it is not, because the real constraint is that the system is expensive to verify — and no amount of QA effort changes that.
Testability is an architectural property. Some systems can be verified quickly and cheaply; others cannot, and the difference is decided by design choices made long before any test was written.
Common architectural sources of low verification capacity:
Tight coupling between services. If you cannot deploy or test service A without a working service B, C, and D, every verification activity requires assembling the whole system. That makes tests slow, environments scarce, and failures ambiguous.
Unstable or shared test environments. A staging environment shared by six teams is a serialized resource. Everyone waits, test data interferes, and failures are often caused by someone else's deploy — which trains the whole organization to distrust failures.
Poor test data management. If realistic test data requires a manual request, a production copy, or a two-day setup, everything data-dependent is expensive to test by construction. This is the most common hidden cause of slow verification.
Undocumented or implicit contracts. When boundaries are defined by "whatever the producer currently returns," every producer change is potentially breaking, and the only way to find out is to run everything.
Weak observability. If you cannot tell what the system did, you cannot verify it efficiently — and you cannot detect production failures fast enough to trade pre-production depth for post-release detection.
Slow pipelines, no isolation, and nondeterministic integrations. If deploying to an isolated environment takes forty minutes, verification is rate-limited by deployment rather than testing. Third-party sandboxes that are slow, rate-limited, or occasionally down inject failure into every test that touches them.
Testability as an investment with compounding returns
The technical enablers that raise verification capacity are mostly familiar. What is less familiar is treating them as verification infrastructure with a measurable return, rather than as engineering hygiene that competes with feature work.
Deterministic interfaces. Explicit inputs and outputs, no hidden global state, no reliance on wall-clock time or ambient configuration. Deterministic code is cheap to test and, not incidentally, cheap for an AI agent to modify correctly.
Consumer-driven contract testing. Each consumer declares what it needs from a provider; the provider verifies against all declared expectations in its own pipeline. This converts "run everything to see if anything broke" into a fast, local check, and it is one of the highest-leverage investments available to a team running multiple services with rising change volume.
Dependency virtualization. Recorded or simulated third-party behavior — including error responses, timeouts, and rate limits — removes external nondeterminism and makes failure-path testing possible at all.
Ephemeral environments. A per-branch environment created on demand and destroyed after use removes the serialized-resource problem entirely. This is often the single highest-impact change available to a team whose QA appears to be the bottleneck, because it converts a queue into parallel capacity.
Seeded, versioned test data. Deterministic fixtures that can be created in seconds, plus at least one dataset shaped like production in volume and distribution, so that migration and performance behavior can be validated before it matters.
Observability and traceability. Structured logs, distributed tracing, and correlation IDs that answer "what actually happened" in minutes rather than hours. Trace-level visibility also reveals which code paths a test exercised — the raw material for test impact analysis. Feature flags and clean isolation boundaries then reduce the confidence threshold required at release time, as discussed in Part VI.
The connection to AI velocity is direct and worth making explicit to a board or leadership team: architectural testability determines the exchange rate between generated code and shipped value. Two organizations can adopt identical AI tooling and get very different outcomes, because one of them can verify a change in eight minutes and the other needs two days and a free staging slot. DORA's finding that AI acts as an amplifier of existing organizational strengths and weaknesses is, in large part, this. The 2025 State of AI-assisted Software Development report finds that AI's primary role is that of an amplifier, magnifying the strengths of high-performing organizations and the dysfunctions of struggling ones. Testability is one of the things being amplified.
[Internal link opportunity: SaaS testing]
Part IX — CI/CD Becomes the Next Bottleneck
Once teams stabilize verification strategy, the constraint frequently relocates again — to the pipeline.
The economics are unforgiving. Pipeline load scales with the product of change frequency and suite size, and AI-assisted development pushes both upward at once. Teams generate more pull requests, and they add more tests to compensate for uncertainty about generated code. A pipeline that comfortably handled 40 runs a day at 12 minutes is a different animal at 120 runs a day at 25 minutes.
The failure modes compound. Feedback slows, so engineers context-switch and return later, lengthening cycle time far beyond the pipeline duration itself. Queues form. Infrastructure cost rises faster than anyone budgeted, because parallelism is the first response and parallelism is billed. Merge delays increase the number of changes in flight, raising interaction risk. And more executions per day means more opportunities for flaky tests to fire.
CircleCI's Q2 2026 pulse data, drawn from more than 20 million workflows, describes exactly this plateau: main-branch throughput stayed entirely flat, main-branch success rates improved modestly from 70.8% in Q1 to 76.7% in Q2 but remained well below the mid-80s results of 2023–2024, and validation remains the industry's biggest bottleneck — teams continue to generate more code than they can safely integrate and ship.
Smarter execution, and its limits
The response is not "run fewer tests." It is to make execution proportional to what changed, and to move expensive validation off the critical path where it is safe to do so.
Test impact analysis and affected-test selection. Using coverage data or dependency graphs, determine which tests can possibly be affected by a given diff, and run those on the pull request. This is the highest-leverage technique available and is well supported in most major build systems, but it depends on accurate mapping and degrades badly when the code has hidden coupling through shared state, configuration, or the database.
Parallelization and sharding. Split the suite across workers. Effective, bounded by Amdahl's law and by shared resources — twenty parallel workers hitting one database do not run twenty times faster. Sharding also introduces new failure modes around test isolation.
Caching and incremental builds. Often the largest single win, and usually underexploited.
Change-aware routing and smoke gates. Different pipelines for different risk classes, per Part V — a copy change should not enter the same pipeline as a migration — with a three-minute smoke suite catching obvious breakage before committing thirty minutes of compute.
Post-merge and scheduled deep regression. Move the full suite off the pull request path onto main or a nightly cadence, trading detection latency for feedback speed.
Risk-triggered suites. Touching payments triggers the payments suite regardless of what impact analysis says.
Each of these has a real trade-off, and selective execution is not automatically safe. Test impact analysis will miss coupling it cannot see. Post-merge testing means broken code reaches main, which is only acceptable if reverting is genuinely fast and if main is not continuously deployed without a gate. Sharding creates ordering dependencies that produce flakiness.
The mitigations must be deliberate: run the full suite on a fixed cadence regardless of what selection says, so gaps in the impact model surface within a day rather than a quarter; treat every escaped defect as a test-selection audit, because a defect that reached production while its test existed but was not selected means the impact model has a bug; and keep risk-triggered overrides for critical modules non-negotiable.
The founder-level version: you are buying feedback speed with detection latency, and that trade is only sound if you can detect and reverse quickly. Which brings the argument back to containment and observability, again.
Part X — Flaky Tests Become a Tax on AI Velocity
A flaky test is one that produces different results on the same code. It is a small annoyance at low change volume and a structural problem at high change volume, because its cost scales with how often the suite runs.
Consider the arithmetic. Take a suite flaky enough that roughly one in eight full runs shows a spurious red. At 30 pipeline runs per day that is four false failures daily; at 120 runs — the AI-accelerated case — sixteen. Each costs a rerun, a context switch, and a decision about whether it is real. The tests did not get worse. The rate of change did.
Published data suggests this is not a fringe problem. Research on Google's continuous integration infrastructure has been widely reported to show that roughly 16% of tests exhibit some level of flakiness, and the majority of red builds teams investigate are false alarms rather than regressions. Microsoft research on large-scale CI systems has been cited as attributing roughly 25% of test failures to flakiness rather than actual code defects. Bitrise's 2025 Mobile Insights analysis of over 10 million builds across three and a half years found the proportion of teams experiencing test flakiness grew from 10% in 2022 to 26% in 2025, while pipeline complexity increased 23%. Slack's engineering team has reported reducing flaky mobile test failures from 56.76% to 3.85% after building automated detection and suppression. Treat the specific percentages as indicative rather than universal — they come from very different codebases and measurement approaches — but the direction is consistent across every source.
Confidence erosion
The direct costs — reruns, investigation time, pipeline delay, compute spend — are the visible part and the smaller part.
The larger cost is confidence erosion. It follows a predictable progression. First, engineers investigate every failure. Then, having found several to be spurious, they start rerunning first and investigating second. Then rerunning becomes reflexive. Then someone marks a test as known-flaky and stops looking at it. Then a team stops reading the failure list carefully at all, because the signal-to-noise ratio no longer justifies the attention.
At that point the organization has automation without verification. The tests still run. The pipeline still reports. But no decision is actually being informed by the output, and a real regression will be reruns-away from merging.
This matters more in an AI-accelerated environment for a specific reason: when engineers are less familiar with the code being changed, the test suite is carrying more of the verification load than it used to. A team that could once catch a bad change through reviewer intuition now depends more heavily on the suite. Eroding trust in the suite at the same moment its importance increases is a bad combination.
Sources, and the distinction that matters
Flakiness has recognizable causes: timing and race conditions around asynchronous behavior; environment instability and resource contention on shared or under-provisioned runners; shared mutable state that makes outcomes depend on execution order; brittle UI selectors; unreliable external dependencies; and inadequate test data isolation.
The critical distinction, and the one most often missed: some flakiness is a test defect, and some is the product telling you the truth.
A test that intermittently fails because it asserts before an async operation completes is a test problem. A test that intermittently fails because the application has a genuine race condition under concurrent access is a product problem that happens to be surfacing through the test. Automatically retrying both makes the first disappear and the second invisible — and the second is a production incident waiting for the right traffic pattern.
This is why blanket auto-retry policies are dangerous. Retries are a legitimate short-term containment measure, but only when paired with three things: every retry is recorded, so flakiness is measured rather than hidden; retried tests enter a triage queue with an owner rather than a backlog; and each is classified as test defect or product defect before being closed.
Practically: quarantine flaky tests out of the blocking path rather than deleting them, with a time limit and an owner, so pipeline signal stays clean while the problem stays visible; track first-pass success rate — the share of runs passing without any retry — as a headline health metric, because it is what correlates with whether engineers trust the suite; and treat sustained flakiness in a critical-path test as release-blocking rather than a maintenance ticket.
[Internal link opportunity: Playwright testing]
Part XI — The Economics of Verification
Founders reason in trade-offs, so it is worth translating all of this into the language of cost and return.
Quality engineering is often budgeted as a cost center — a tax on shipping. The more accurate framing is that verification is the mechanism that converts engineering output into deliverable value. Code that has not been verified is inventory, not product. It has consumed cost and delivered nothing.
The cost of insufficient verification is rarely a single line item. It shows up as delayed releases while defects are found late and fixed under pressure; engineering rework, the most expensive form of engineering time because it displaces new work; support load that scales with escaped defects; incident response, including the disproportionate cost of out-of-hours work; churn and expansion loss where reliability shapes renewals; SLA credits; security incidents, whose cost distribution has a long tail; and opportunity cost — usually the largest component and never in any budget — the features not built because the team was fixing the last release.
The cost of excessive verification is equally real and frequently ignored in quality-focused writing. A four-week release cycle in a market where competitors ship weekly is a strategic liability. Gates engineers perceive as theatre get routed around, producing the cost of the process with none of the benefit.
The goal is not zero defects. The goal is reliable delivery velocity — the maximum rate at which valuable, trustworthy change reaches customers.
A useful heuristic — a way to structure the conversation, not a formula to compute:
Optimize for value delivered × confidence × speed, recognizing that pushing any one term to its maximum drives the others toward zero.
Maximum speed with no confidence produces incidents that consume the speed. Maximum confidence with no speed produces a system nobody wants to change. The interesting work is at the interior optimum, and finding it requires knowing where your constraint currently sits — which is Part XIII.
One implication deserves emphasis. Because the terms multiply rather than add, the highest-return investment is almost always in the weakest term. An organization with excellent test coverage and a two-week environment queue does not need more tests. An organization shipping daily with no observability does not need faster pipelines. Uniform investment across all three is usually a sign that nobody has diagnosed the constraint.
Part XII — How to Know QA Has Become Your Bottleneck
No single metric proves a verification bottleneck. Cycle time can lengthen for a dozen reasons. Escaped defects can rise because usage grew. What identifies a bottleneck is a pattern across categories, and the categories matter because each one points toward a different intervention.
| Category | Signal | What it usually indicates |
|---|---|---|
| Flow | Pull requests wait far longer for validation than they took to write | Arrival rate exceeds clearance rate at review or CI |
| Flow | QA receives work in large end-of-sprint bursts rather than continuously | Batching upstream; verification is being treated as a phase |
| Flow | Feature-branch activity rising while merges to main are flat or falling | The classic AI-era signature: production up, integration constrained |
| Reliability | Escaped defects increasing, especially in areas with recent change | Verification depth is not matching risk |
| Reliability | Reruns are routine and first-pass success rate is low | Flakiness is consuming capacity and eroding trust |
| Organizational | The instruction to QA is "test faster" rather than "improve the system" | The constraint is being managed as an effort problem |
| Organizational | Automation engineers spend most of their time on maintenance | Suite has outgrown its architecture; net capacity is falling |
| Behavioral | Regression depth quietly reduced to meet a date | The system is above capacity and adapting by lowering standards |
| Behavioral | Known flaky tests are normalized and unowned | Confidence erosion is well advanced |
| Behavioral | Changes are released in large batches because splitting them is operationally expensive | Deployment and verification cost per release is too high |
The behavioral signals are the most diagnostic and the least measured, because they are adaptations rather than failures. Nobody announces that regression depth was reduced. It simply happens, sprint after sprint, and each individual decision is defensible. By the time it shows up as an incident, the practice has been normalized for months.
A practical instruction for leadership: ask about the behavioral signals directly, in a setting where the honest answer is safe. "When was the last time we shipped something without the testing we would normally do, and why?" produces more useful information than any dashboard.
Part XIII — A CTO Diagnostic: Where Is Your Real Constraint?
"QA is the bottleneck" is a diagnosis with at least five distinct underlying causes, each requiring a different intervention. Getting this wrong is expensive: hiring testers to solve an environment problem adds cost without adding throughput.
Examine five dimensions. Resist the urge to score them numerically — a composite number would create false precision and hide the one dimension that actually matters.
1. Change Arrival Rate. What it means: how much meaningful change enters verification per unit time, and in what shape — size, risk distribution, burstiness. Failure looks like: work arriving faster than it can be processed, in large batches clustered at the end of a cycle. Evidence: pull requests opened per week over twelve months; median and 90th-percentile PR size; arrival distribution across the sprint; share of changes touching high-risk areas. Interventions: batch-size discipline; splitting changes at the source; risk classification so low-risk change bypasses expensive paths; sometimes constraining parallel work in progress.
2. Test Execution Capacity. What it means: throughput and latency of automated verification. Failure looks like: queued pipelines, long feedback loops, engineers batching to avoid waiting. Evidence: pipeline duration trend; queue wait time; compute cost per merged change; first-pass success rate; share of runtime spent on tests that have never caught a real defect. Interventions: test impact analysis; parallelization; caching; moving deep suites off the critical path; deleting tests that carry cost without signal.
3. Investigation Capacity. What it means: human ability to analyze failures, review changes, and explore uncertainty. Failure looks like: failures triaged shallowly or not at all; reviews that approve without engaging; no exploratory work because everyone is clearing a queue. Evidence: time from failure to classification; review pickup time and depth; hours spent investigating versus executing; number of unowned known-flaky tests. Interventions: reduce noise so investigation is worth doing; automate failure clustering; protect time for exploration; add specialist capacity where a skill is genuinely missing.
4. Environment Capacity. What it means: availability of environments and data suitable for verification. Failure looks like: teams scheduling access; testing blocked by someone else's deploy; results nobody trusts because environment state is unknown. Evidence: environment wait time; share of failures traced to environment rather than code; time to provision a usable environment with data; how long since the test dataset resembled production. Interventions: ephemeral per-branch environments; seeded deterministic data; dependency virtualization; production-shaped datasets.
5. Release Decision Capacity. What it means: the ability to convert evidence into a go/no-go decision and to contain the consequences of being wrong. Failure looks like: releases waiting on a person rather than evidence; sign-off as ritual with no defined criteria; large batches because releasing is expensive; rollback nobody has rehearsed. Evidence: time from "verification complete" to production; changes per release; whether release criteria are written down; measured — not assumed — rollback time; share of releases with a canary or staged rollout. Interventions: written release criteria per risk class; delegated authority within defined bounds; flags, canaries, rollback; smaller, more frequent releases.
Use this as a leadership conversation, not a report. Ask each owner to describe their evidence for their dimension, and look for the one where the evidence is weakest or entirely absent. In most organizations one dimension dominates — and it is usually not the one receiving investment.
[Visual concept: A five-segment horizontal capacity diagram showing change flowing left to right through arrival, execution, investigation, environments, and release decision. Each segment is drawn at a width proportional to its capacity, so the narrowest segment visually identifies the constraint, with change units visibly backing up in front of it.]
Part XIV — When More QA Engineers Help, and When They Don't
Headcount is the default response to a throughput problem, and it is sometimes exactly right. The question worth asking first is whether you have a capacity problem or a system design problem.
A capacity problem means the system works and there is not enough of it. Adding capacity produces roughly proportional output. A system design problem means each additional unit of capacity is consumed by the system's own friction. Adding people produces marginal output, and sometimes negative output, because coordination cost rises.
| Symptom | Capacity problem | System design problem |
|---|---|---|
| Testers are busy but effective; work is well-targeted; findings are valuable | ✓ Hire | |
| Product scope grew genuinely — new platforms, regions, or compliance obligations | ✓ Hire | |
| A specific skill is missing entirely — security testing, performance engineering, accessibility | ✓ Hire specialists | |
| Exploratory capacity is zero because all human time goes to regression execution | Partly | Mostly — automate the regression first |
| Testers spend their time waiting for environments | ✓ Fix environments | |
| Most of automation's time goes to maintaining brittle tests | ✓ Fix suite architecture | |
| Failures are frequent but usually spurious | ✓ Fix flakiness and instability | |
| Releases are large because deployment is expensive | ✓ Fix release engineering | |
| Verification requires assembling the entire system | ✓ Fix architecture and contracts |
The heuristic worth remembering: if a new hire would spend their first month waiting, maintaining, or re-running, you have a system design problem. Hiring into it converts a bottleneck into a more expensive bottleneck.
The converse trap is equally real. Teams that have correctly identified a system design problem sometimes spend two years re-architecting while under-resourced, and never reach the point where the system works. Both interventions are usually needed. The sequencing is what matters, and the sequencing should follow the constraint.
Part XV — Designing a QA System for AI-Accelerated Development
A verification system built for this environment has seven working parts, and they are interdependent: weakening any one of them shifts load onto the others.
Fast feedback on every change, in minutes, covering the deterministic checks that catch the majority of ordinary mistakes. Risk classification that routes changes to proportionate depth rather than uniform ceremony. Layered automation organized as a portfolio, with contract tests carrying the load at service boundaries and end-to-end tests reserved for journeys that genuinely matter. Independent validation — at least one link in the chain from requirement to release that is not derived from the same interpretation that produced the implementation. Observability sufficient to detect in production what testing did not catch, quickly enough to matter. Exploration, scheduled and mission-driven, aimed at ambiguity and novelty. Release safeguards — flags, staged rollout, rehearsed rollback — that lower the confidence threshold required to ship.
There is no universal configuration. The right system depends on what failure costs you and how fast you learn.
Early-stage SaaS (under ~15 engineers). The dominant risk is building the wrong thing, not breaking the right thing. Invest in fast CI, a handful of end-to-end tests covering signup, payment, and the core value path, feature flags, error monitoring, and the ability to deploy and roll back in minutes. Skip formal risk classification — everyone already knows the risky areas. Do not skip deploy and rollback capability: it is the cheapest verification capacity available and gets more expensive to retrofit every quarter.
Growth-stage SaaS (roughly 15–100 engineers). This is where the bottleneck described here bites hardest, because change volume scaled and the verification system did not. Priorities: ephemeral environments to break the shared-staging queue, contract testing as services multiply, explicit risk classification, test impact analysis to keep CI fast, deliberate attention to flakiness before trust erodes, and a first real investment in exploratory capacity. Testability debt becomes visible at this stage, and paying it down has the highest return here.
Enterprise platforms. Scale turns the problem from throughput into coordination: many teams, shared components, long-lived integrations, consumers who cannot be upgraded in lockstep. Contract testing, versioning discipline, and service-level ownership of quality matter more than any central QA function, and full-system validation on a cadence becomes non-negotiable because no single team sees the whole regression surface.
Regulated or high-consequence systems. Evidence and traceability become part of the deliverable. Risk classification is formalized, independent verification is often mandatory rather than advisable, and the release decision has named accountability. Regulated does not mean slow — but the trade-off point sits differently, and containment must satisfy an auditor as well as an engineer.
A six-person startup should not copy the verification system of a global payments platform. But both need an explicit answer to the same question: how does rapid code generation become reliable release in this organization? The failure mode is not choosing the wrong system. It is never having chosen one.
Part XVI — The 90-Day Verification Capacity Program
What follows is organized by outcome rather than by week, because the sequencing that matters is diagnostic before remedial. Deliberately absent are percentage improvement targets; the honest answer is that the size of the gain depends entirely on where your constraint sits.
| Phase | Focus | Primary output | What leadership should learn |
|---|---|---|---|
| 1. Make the constraint visible (weeks 1–3) | Measurement, not fixing | A map of change flow from commit to production, with wait time at each stage | Where change actually waits — usually not where people assume |
| 2. Remove verification waste (weeks 3–8) | Reclaiming existing capacity | Faster, more trustworthy pipeline; stabilized critical automation | How much capacity was being consumed by noise rather than work |
| 3. Introduce risk-aware verification (weeks 6–11) | Allocating capacity by risk | Change classification in use; defined critical journeys; contract coverage at key boundaries | Whether verification depth has been matching actual risk |
| 4. Add production confidence (weeks 9–13) | Lowering the cost of being wrong | Flags, rollback, canaries where appropriate, synthetic checks, incident feedback loop | How quickly you would actually detect and reverse a bad release |
Phase One — make the constraint visible. Map the flow: pull requests opened, time to first review, time in review, CI duration and queue time, environment wait, testing duration, time from ready to released. Inventory the suites — runtime, ownership, failure history, and how many have never caught a real defect. Measure flakiness by recording every retry. Pull two quarters of escaped defects and classify them by what would have caught them. Name the journeys whose failure would be unacceptable. Resist fixing anything for three weeks: the diagnosis is the deliverable, and teams that skip it reliably optimize the wrong stage.
Phase Two — remove verification waste. Delete or quarantine tests carrying cost without signal. Stabilize flaky tests on critical paths, classifying each as test defect or product defect. Fix test data provisioning — usually the largest single source of hidden delay. Parallelize and cache expensive suites. Attack whichever environment constraint the map surfaced. Almost every organization finds real capacity here without new investment.
Phase Three — introduce risk-aware verification. Build the change classification from Part V, informed by Phase One's escaped-defect analysis. Define and automate the critical journeys. Add contract tests at the boundaries where integration defects historically originated. Route pipelines by risk class.
Phase Four — add production confidence. Improve telemetry on the paths that matter. Flag anything risky. Rehearse rollback rather than assuming it. Add canary or staged rollout where traffic volume makes it meaningful, and synthetic checks on critical journeys. Close the loop: every incident updates the risk model.
The most valuable output of ninety days is not the improvements. It is that the organization now knows where its constraint sits and can watch it move.
Part XVII — What AI Should Actually Do Inside QA
Having argued that AI-generated tests do not by themselves solve the bottleneck, it is worth being equally clear about where AI genuinely expands verification capacity. The distinction is not whether to use AI in QA — it is which function AI is performing, because the governance requirements differ sharply by function.
AI is well suited to test case ideation (proposing scenarios a human filters), test and fixture generation for well-specified interfaces, log and trace analysis across large volumes of failure output, failure clustering that turns two hundred red tests into six root causes, test maintenance assistance when interfaces change, requirements analysis that surfaces ambiguity before it becomes a shared assumption, risk identification by summarizing what a diff touches and which consumers depend on it, synthetic test data generation with realistic shape and distribution, code-change summarization to reduce reviewer load, test impact suggestions, and exploratory session preparation.
Several of these attack problems raised earlier. Failure clustering addresses investigation capacity. Change summarization and dependency analysis partially restore the risk metadata that familiarity used to supply. Requirements analysis attacks the shared-assumption problem — provided the output goes to a human for judgment rather than back into generation.
The governance question is best framed as a ladder, with requirements rising at each rung:
AI generating checks. Lowest risk. Output is reviewable, and a bad test is visible. Requires review discipline and a bar on merging generated tests nobody has read.
AI evaluating results. Higher risk, because errors are silent — an AI that classifies a failure as flaky and suppresses it can hide a real defect. Requires sampling, audit trails, and measured classification accuracy against known outcomes.
AI recommending risk. Higher still, because the recommendation determines what verification happens at all. Requires that recommendations stay advisory, that overrides be easy, and that every escaped defect audit the recommendation that preceded it.
AI making release decisions. Strongest controls, and for most organizations in 2026 this should remain bounded: automatic promotion within defined risk classes, explicit human accountability outside them. The standard is evidence — can you reconstruct, after an incident, what the system knew and why it proceeded?
The general principle: the further AI moves from generating artifacts toward making judgments, the more the organization needs auditable evidence rather than trust. AI belongs inside the verification strategy as a capacity multiplier. It does not become the strategy.
[Internal link opportunity: AI application testing]
Part XVIII — Software Production Gets Cheap; Trust Does Not
Keep the horizon short and the claims modest — 2026 to 2028, not a decade.
The observable trend is that the cost of producing a working software change keeps falling. If it continues, organizations will produce more of everything: more features, experiments, internal tools, integrations, small services, and custom software that previously was not worth building. Abundance in production is a reasonable extrapolation from current evidence.
What follows is inference rather than measurement: when producing an asset becomes cheap, the scarce input shifts to whatever gates its use. For software, that gate is trust — the justified belief that a change will behave as intended in front of real customers with real data and real money.
Trust does not get cheaper at the same rate, for a structural reason. Producing a change is a bounded task with a local answer. Establishing that a change is safe requires knowledge of the whole system, its history, its users, and its failure modes — a fundamentally harder problem, and not obviously one that falls at the same rate.
The most concrete signal available today is the Veracode series: syntax pass rates climbing from about 50% to 95% since 2023 while security pass rates stayed flat between 45% and 55% regardless of model generation. That is one property in one benchmark and should not be over-generalized, but it points toward production capability and assurance capability improving on different curves.
If that holds even partially, advantage accrues to organizations that can characterize the risk of a change before shipping it, detect failure in minutes rather than days, protect customer data as velocity rises, and release frequently without losing the ability to say why they believed it was safe.
That makes quality engineering more strategic, not less. Not as a gate, and not as a department that says no — as the discipline that determines how much of an organization's engineering capacity actually converts into delivered value.
The Scarce Resource Is No Longer Code
Return to the company in the opening. Nothing about its situation was a failure of effort or competence. It made one part of its delivery system dramatically faster and left the rest unchanged, and the system responded as systems do: the constraint relocated, queues formed in front of it, and the people in those queues adapted by lowering depth rather than raising alarm.
The lesson generalizes. Code throughput is not verified change throughput. An organization that doubles its ability to produce changes and does not touch its ability to establish confidence in them has not doubled its velocity. It has doubled the pressure on whatever it did not upgrade — and in the CircleCI data, in the LinearB data, and in the DORA finding that AI amplifies whatever system it lands in, that pressure is measurable at industry scale.
None of this is an argument against AI-assisted development, and it is not a claim that AI-generated code is inherently defective. The argument holds even if generated code were indistinguishable in quality from human-written code, because the problem is throughput mismatch, not defect density. It is an argument that engineering leverage and verification capacity are two different investments, and that only one of them has been receiving attention.
The organizations that win the next few years will not be the ones producing the most code. They will be the ones that can take a rapidly generated change, understand what it could break, verify it proportionately, ship it behind controls that make failure survivable, and know within minutes whether they were right.
AI has made writing software cheap. Quality engineering decides how much of that output an organization can actually stand behind.
QAtronic works with SaaS and technology companies in the US and Europe on exactly this problem: quality engineering strategy, test automation, software testing, security testing, QA process design, and dedicated QA teams that integrate with existing engineering organizations rather than sitting beside them.
If increasing development velocity is generating more verification work than your current system can absorb, the useful first step is diagnosis rather than procurement — establishing whether the constraint actually sits in automation, architecture, environments, test strategy, pipeline design, or QA capacity, since each points to a different intervention. That assessment is something we can help with, and it is worth doing before adding either headcount or tooling.
A note on evidence: Vendor benchmark figures cited in this article reflect each provider’s own datasets and may not represent the entire software industry. The Verification Pressure Ratio and other diagnostic models introduced here are QAtronic’s analytical frameworks rather than established industry standards. Hypothetical examples are identified as such.
Sources and Further Reading
- DORA, State of AI-assisted Software Development (2025) and the companion DORA AI Capabilities Model.
- METR, Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity (July 2025) and We are Changing our Developer Productivity Experiment Design (February 2026).
- CircleCI, 2026 State of Software Delivery (analysis of 28M+ CI workflows) and the Q2 2026 pulse update.
- LinearB, 2026 Engineering Benchmarks Report.
- GitClear, The Maintainability Gap: 2026 AI Code Quality Research.
- Veracode, 2025 GenAI Code Security Report and the Spring 2026 update.
- OWASP, Top 10 for Large Language Model Applications.