The State of API Testing in CI 2026
How teams run contract, integration, and mocked API tests in pipelines, and why the network boundary is the single flakiest thing in continuous integration.
Executive summary
API testing sits at an awkward seam in continuous integration: the tests that give the most confidence are the ones that cross a network boundary, and the network boundary is the single most unreliable thing in any pipeline. A unit test that runs entirely in process is deterministic by construction, but the moment a test opens a socket to a dependency, it inherits every failure mode of the wire, DNS, connection resets, timeouts, throttling, and the dependency simply being down. As more suites run on every push, the question is no longer whether to test APIs in CI but how to do it without paying a flake tax on every merge.
The teams that get this right in 2026 draw a clear line between two kinds of test that are often blurred together. Contract tests pin the shape of an interface, the fields, types, and status codes a consumer and provider have agreed on, cheaply and deterministically, without crossing a real network. Integration tests exercise real wire behavior against a live or containerized dependency, and they are where the confidence and the flakiness both concentrate. The strongest pipelines mock aggressively at the unit boundary and reserve real calls for a small, well-instrumented set of integration legs rather than letting live calls leak into the broad test body.
This report quantifies where API-test time and flakiness actually go. It shows why mocked tests are roughly an order of magnitude more stable than live ones, why a small minority of integration legs consume the majority of API-test minutes and almost all of the flakiness, and why the failures that survive good mocking discipline are mechanical retries rather than real regressions. That last category is the crucial one, because it is exactly the class a self-healing runner absorbs without a human ever seeing a red check.
The economic stakes follow from the flake rate. Every spurious red build from a network blip costs a re-run and, far more expensively, an engineer context switch when a green change comes back red for no reason. In an API-heavy suite where the network dominates the flake budget, that tax recurs on a large fraction of merges, and it is almost entirely avoidable. The fix is partly discipline, mocking and contract tests at the right boundary, and partly infrastructure, a runner that retries the genuinely transient remainder on a fresh environment.
For engineering leaders the practical message is that API-test reliability is mostly an architecture and runner-layer problem, not a test-authoring problem. Quarantining flaky API tests is the wrong first move, because the tests usually are not broken; the network hiccuped. The teams that internalize this stop treating every red integration test as a bug to fix, move the network behind a mock wherever a mock suffices, and let the runner clear the mechanical failures that remain.
Modeled breakdown of flaky failures in API-heavy CI suites. · Source: Latchkey analysis (modeled)
Modeled share of test runs needing at least one retry. · Source: Latchkey analysis (modeled)
Email me the report
The full report is right here on this page, free. Want the link in your inbox to read later or share, plus new Latchkey reports as they drop? Drop your email and we will send it over.
Sent! Check your inbox for the report link.
No spam. Unsubscribe anytime.
The network is the flake budget
In API-heavy suites the large majority of intermittent failures never reach a real assertion. They are upstream timeouts, connection resets, and throttling responses that have nothing to do with the code under test. When the flake sources are broken out, real assertion failures are the smallest slice, and the network categories, dependency timeouts, DNS and connection resets, and rate limiting, dominate the rest.
This matters because it inverts the usual response to a flaky test. The instinct when a test fails intermittently is to suspect the test, quarantine it, mark it as known-flaky, or rewrite it. But in an API suite the test is usually fine; the wire hiccuped. Quarantining it discards real coverage to silence a failure the test was right to surface, and it trains the team to ignore exactly the integration legs that catch real regressions.
The correct fix has two parts, and neither is rewriting the test. First, isolate the network at the right boundary so that most tests never cross it, which removes the bulk of the flake sources outright. Second, let the runner absorb the genuinely transient remainder by retrying on a clean environment, so the handful of real network blips that survive never reach a developer. The flake-source breakdown chart shows how little of the budget is actually a code problem.
- Real assertion failures are the smallest slice of an API-heavy flake budget; the network categories dominate.
- Quarantining network-flaky tests discards real coverage to silence a correct failure.
- The fix is isolation at the boundary plus runner-side retry, not test rewriting.
Mock at the unit boundary, integrate sparingly
A mocked API test retries roughly an order of magnitude less often than one that calls a live upstream, because it removes every source of non-determinism except the code itself. When the retry rate is read by strategy, an in-process mock barely retries at all, a local stub server is nearly as stable, a containerized dependency is meaningfully flakier, and a live upstream call retries many times more often than the mock.
The lesson is a layering discipline, not a blanket rule against real calls. Mock exhaustively at the unit level so the broad body of the suite is fast and stable, giving developers feedback they can trust on every push. Then reserve real wire calls for a deliberately small set of integration legs that exist specifically to verify the things a mock cannot, serialization, auth handshakes, pagination, and the actual contract the dependency honors.
The failure mode to avoid is letting live calls leak out of that small set and into the broad test body. It happens gradually, a unit test that quietly reaches a real service for convenience, an integration helper reused in places it should not be, and each leak imports the live-call retry rate into a test that should have been deterministic. The mock-versus-live retry chart is the argument for keeping that boundary sharp.
- In-process mocks retry far less than live upstream calls, isolating non-determinism to the code itself.
- Mock exhaustively at the unit level; reserve real calls for a small, deliberate integration set.
- Guard against live calls leaking into the broad test body and importing their retry rate.
Contract tests are the cheapest confidence you can buy
Pinning the shape of a request and response with a contract test costs almost nothing to run and catches the breaking-change class that integration tests catch slowly and expensively. A contract test asserts that the provider still returns the fields, types, and status codes the consumer depends on, and it does so without standing up the dependency, crossing the network, or paying the integration-test flake rate.
Teams that add a contract layer between consumer and provider find they can shrink the live integration surface without losing the guarantee that actually matters. Many integration tests exist only to catch a provider changing its response shape, and a contract test catches that earlier, faster, and deterministically. Replacing those integration legs with contract assertions both speeds the pipeline and removes their contribution to the flake budget.
Contract tests are not a full substitute for integration tests, and the report does not claim they are. They verify the agreed shape, not the live behavior, so a small set of real integration legs still earns its place for serialization, auth, and timing. But the cost-to-confidence ratio of the contract layer is the best in the API-test plan, which is why the strongest pipelines push as much of the breaking-change guarantee as possible down into it.
Integration legs dominate cost even when they are the minority
Containerized and end-to-end legs are a small share of an API test plan by count but a large share of its minutes and almost all of its flakiness. Each one starts dependencies, warms connections, seeds data, and crosses real boundaries, so a single integration leg can cost more wall-clock and more flake risk than dozens of fast mocked tests combined. The minute-share breakdown shows the containerized and end-to-end legs together consuming the majority of API-test minutes.
The consequence for optimization is that tuning the fast mocked tests, which already run cheaply and stably, returns almost nothing, while right-sizing where the integration legs run returns a great deal. The highest-leverage moves are keeping these legs off slow or expensive runner classes, reusing warmed dependency containers across tests instead of restarting them per test, and parallelizing them only where they are genuinely independent.
There is a cost dimension on top of the time dimension. Because integration legs are slow, they accumulate the most billed minutes, and if they happen to run on a Windows or macOS runner the per-minute multiple compounds the slowness, a Windows minute costs twice a Linux minute and a macOS minute 10 times as much. Pinning OS-agnostic integration work to Linux is often the single biggest cost lever in an API-test plan, and the per-minute cost chart shows how wide that spread is.
- Integration and end-to-end legs are a minority by count but the majority of minutes and flakiness.
- Tuning the fast mocked tests returns little; right-sizing the integration legs returns a lot.
- Pinning OS-agnostic integration work to Linux avoids the Windows and macOS per-minute multiples.
Modeled share of API-test CI minutes by test type. · Source: Latchkey analysis (modeled)
The per-minute price multiplies through a slow API suite
API-test suites are slow by nature, because the integration legs that give them their value are slow by nature. That makes the per-minute price of the runner an unusually important lever for this report specifically: a suite that runs many slow minutes pays the runner rate many times over, so the rate itself becomes a meaningful share of the cost of testing APIs at all.
The published hosted rates spread the price by operating system, with Windows at twice the Linux rate and macOS at 10 times it, and an API suite that drifts onto the premium tiers for no platform-specific reason pays that multiple on every slow integration minute. Because the integration legs are exactly the slow ones, an OS mismatch on those legs is the most expensive mismatch a team can make in an API-test plan.
The managed line on the per-minute cost chart lands below even the cheapest hosted tier, around 69 percent under the hosted Linux rate. For a slow API suite that compounds: the same integration legs run, but every one of their many minutes is cheaper, and the wasted re-run minutes from network flakes are cheaper too. The runner layer is therefore both a reliability lever and a cost lever for API testing at the same time.
Published GitHub-hosted Windows and Linux rates vs a managed alternative. · Source: GitHub Actions pricing + Latchkey rates
Self-healing runners turn network flakes into non-events
The residual failures that survive good mocking discipline are almost all mechanical: a dependency that blipped, a registry that throttled, a DNS lookup that reset. Because these pass on a clean retry, they were never really failures of the code, and the only reason they cost anything is that a naive pipeline surfaces them as red checks and waits for a human to re-run the job.
A self-healing managed runner closes that gap directly. When a step fails on a known-transient network signal, the platform retries it on a fresh environment automatically, before the failure ever reaches the pull request. The developer never loses focus to a spurious red check, the re-run minutes are recovery minutes rather than wasted ones, and the genuinely real assertion failures, the small slice that should reach a human, still do.
This is the architecture that makes the rest of the report safe to follow. Mocking and contract tests shrink the flake budget, but they cannot drive it to zero, because the integration legs that remain must cross a real network and the real network occasionally fails. Auto-healing absorbs that irreducible remainder, and at roughly 69 percent lower cost per minute the wasted re-run time stops being a meaningful line item at all.
Test data races are the flake that mocking does not fix
Not every API-test flake is a network failure. A meaningful slice is a test data race: two tests sharing a record, a fixture that is not isolated per run, or an integration leg that reads state another leg is still mutating. These survive mocking because they are not about the wire at all; they are about shared mutable state in the test environment.
The fix here is isolation rather than retry, and it is worth distinguishing from the network case because retrying a true data race can mask it instead of clearing it. The durable answer is per-test data isolation, unique identifiers per run, transactional rollback or fresh fixtures, and integration legs that own their data rather than sharing a global pool. A clean, single-use runner environment per job also helps, because it removes state bleeding between jobs as a source of races.
The reason this finding belongs alongside the network ones is that the two are easy to conflate and have opposite fixes. A network flake wants a retry on a fresh environment; a data race wants isolation so the race cannot happen. Reading the flake-source breakdown by category, rather than treating all intermittent failures as one bucket, is what lets a team apply the right fix to each and stop trading one flake class for another.
Recommendations
Mock at the unit boundary and keep live calls out of the broad suite
Mock exhaustively at the unit level so the bulk of the suite is fast and deterministic, and reserve real wire calls for a small, deliberate set of integration legs. Audit periodically for live calls that have leaked into unit tests, because each one imports the live-call retry rate into a test that should never flake.
Add a contract layer between every consumer and provider
Pin the agreed request and response shape with contract tests, which cost almost nothing to run and catch breaking changes deterministically. Use the contract layer to shrink the live integration surface to the legs that genuinely need real behavior, lowering both pipeline time and the flake budget.
Right-size and Linux-pin the integration legs
The slow integration and end-to-end legs carry the minutes and the flakiness, so optimize those, not the cheap mocked tests. Keep OS-agnostic integration work on Linux to avoid the Windows and macOS per-minute multiples, and reuse warmed dependency containers instead of restarting them per test.
Auto-heal transient network failures instead of quarantining tests
Most surviving API-test flakes are mechanical network blips that pass on a clean retry. Retry them on a fresh environment at the runner layer so they never reach a developer, and stop quarantining integration tests that were correct to fail when the wire hiccuped.
Isolate test data so races cannot happen
Distinguish data-race flakes from network flakes, because they have opposite fixes. Give each run unique identifiers, roll back or refresh fixtures per test, and let integration legs own their data rather than sharing a global pool, so a retry never masks a race instead of clearing it.
Outlook
Expect the line between contract and integration testing to harden into standard practice over the next two years, the way unit-versus-integration did a decade ago. As API surfaces multiply with service decomposition, the cost of catching a breaking change late grows, and the contract layer is the cheapest place to catch it. Teams that have not yet drawn that line will feel increasing pressure to, because their integration suites will keep absorbing flake and cost that a contract layer would remove.
The reliability story and the runner story will continue to converge. As more API tests run on every push, the irreducible network flake in the integration legs becomes a larger absolute number, and the only scalable answer is a runner layer that retries the transient remainder automatically rather than asking developers to re-run jobs by hand. The teams that treat network flake as an infrastructure responsibility, not a test-authoring failure, will spend far less of their attention on red checks that were never real.
For most teams the durable takeaway is that API-test reliability is bought with architecture and infrastructure, not with heroics. Draw the contract-versus-integration line, mock at the right boundary, Linux-pin and right-size the slow legs, and put a self-healing runner underneath. None of these require rewriting the application, and together they turn the flakiest part of CI into one of the most predictable.
Methodology
This report combines publicly available developer data, including the Stack Overflow Developer Survey figure that 76 percent of professional developers use CI/CD, with published GitHub Actions pricing and Latchkey's analysis of API-test pipelines across managed runner usage. Figures labeled "modeled" reflect typical contract, integration, and mocked-test behavior, expressed as illustrative estimates of direction and magnitude rather than a primary survey, and will vary with suite composition, dependency reliability, and how aggressively a team mocks. Per-minute costs use the published hosted rates and the Latchkey managed rate from the shared pricing spine. Figures labeled "modeled" are illustrative estimates derived from public pricing and typical pipeline shapes, not a primary survey; figures attributed to a named source reflect that source. Pricing reflects published rates at time of writing and should be verified against current provider pricing.
Sources
- Stack Overflow Developer Survey
- GitHub Actions documentation
- GitHub Actions - billing & pricing
- GitLab DevSecOps Survey