Linear overhauls CI to keep pace with AI-written code

Earlier this year, Linear's CTO Tuomas assigned an engineer the issue "CI costs are high" and asked for faster CI too. The reason was that AI coding agents had made it exponentially faster to ship code, but validating those changes with CI had not kept pace, so every pull request waiting on CI became a growing bottleneck that drove up infrastructure costs and left developers and agents waiting longer for feedback.
The result: despite the test suite almost quadrupling since the start of the year, pull request wait time on CI came down from more than 6 minutes to just over 5, while runner time consumed per test was cut roughly in half. The team grouped the work into four areas: upgrading infrastructure and tooling, optimizing the jobs that gate other work, reducing repeated setup, and making test execution more efficient. Linear's codebase is primarily TypeScript, but the team says many of the optimizations apply across languages and toolchains.
On infrastructure and tooling, moving workloads off GitHub Actions to third-party runners with faster CPUs, higher-performance storage and better cache infrastructure made jobs 34% faster on average in a like-for-like comparison of the two days either side of the switch, with some workloads such as tsc dropping 52%. Switching to tsgo, the native TypeScript compiler, cut the weekly median of the tsc check by 73%, moving the bottleneck off typechecking entirely. Custom lint rules that depended on TypeScript type information were rewritten to use static analysis over the abstract syntax tree instead, letting ESLint drop TypeScript entirely; that cut API lint time by 68% and full-repository lint time by 55%, with a large drop in memory usage too. Removing the dependency on type information also made a later move to Oxlint easier, which further reduced CI runner-minutes spent on linting.
On the jobs that gate other work, capping the fetch depth of change-detection jobs took the slowest of these gates from 94 seconds to 20, and removing checkout entirely from jobs that never needed a working tree cut their time from 27 seconds to 7; a sparse, blobless checkout with limited history saved roughly 11 more seconds on commit-push and merge-queue events. After the runner switch, checkout with actions/checkout sometimes hung because the third-party runners sit outside GitHub's network and rely on a direct IP link that the provider traced to intermittent degradation; Linear replaced it with its own composite action that retries with backoff and sets GIT_HTTP_LOW_SPEED_LIMIT and GIT_HTTP_LOW_SPEED_TIME so a stalled connection aborts after about 30 seconds instead of hanging, plus a persistent git mirror cache. Moving the write of cache markers out of the final gating check and into a job that runs after test shards finish, but gates nothing, shaved 42 seconds off the merge path for every API pull request and merge-queue entry. Combined, the critical-path changes took roughly a minute off the required check for API pull requests on cache misses.
On repeated setup, API test shards had each spent 7 to 8 seconds installing the same Postgres client with apt on every run; moving it into a small CI base image with Node and the client removed that cost. The API test workflow had been installing Linear's entire pnpm-workspace monorepo even though it only needed the API package, so restricting the install cut pnpm install from 44-73 seconds to 16-18 seconds. Caching node_modules turned out to be slower than rebuilding, since even a cache hit took about 28 seconds to restore against roughly 7.5 seconds for a filtered install, so the team dropped the cache. Together those three changes cut per-shard setup time by roughly 44%, from 110-140 seconds to 67-73 seconds. Separately, API containers that had been replaying the full database migration history on every run switched to loading a generated schema snapshot and bootstrap file, cutting database setup from roughly 12 seconds to 1-2 seconds per container. Seven independent short checks that were each starting a runner, checking out the repository and installing dependencies were consolidated into two jobs running the same tasks concurrently; based on June usage, that saved roughly 87,000 runner-minutes a month, equivalent to 11.8% of total CI usage.
On test execution, Vitest distributes work by file rather than by test duration, so a few unusually large files could dominate a shard and hold up the whole suite. After splitting large files and moving from four shards (already up from three earlier in the year) to eight, the critical job got roughly 19% faster and 19% cheaper in an initial benchmark, and a week later the slowest shard dropped from 5.25 minutes to 4.33 minutes. The largest single change was an opt-in Vitest project with isolate: false, letting safe test files share a module registry within a worker instead of rebuilding the entity, GraphQL and decorator graph for every file; it was worth roughly 17% in monthly savings, dropped the slowest shard from roughly 300-379 seconds to about 195 seconds, and cut total API-shard runner time from about 32.8 to 22 minutes per run. It was also the riskiest change for correctness: eligibility required an explicit opt-in comment on every file plus added teardown for shared state, and files using fake timers or unsafe shared state were left in the isolated project. Because agents now write most of Linear's tests, the team also updated its agent skills so generated tests follow the same isolation constraints by default.
Linear says that without this year's CI work, today's test suite would take roughly 11 minutes, close to double what developers wait now, and that the codebase keeps growing at roughly 2,000 new tests a week, so keeping CI fast will stay a continued effort. The eight-shard split only paid off because per-shard setup time was already low: at the old 110-140 second setup cost, eight shards would have spent 15-19 minutes of runner time on setup alone, more than the tests themselves, whereas setup now takes around 40 seconds per shard.
Key facts
- Despite the test suite almost quadrupling since the start of the year, Linear cut pull request wait time on CI from more than 6 minutes to just over 5, while cutting runner time per test roughly in half.
- Moving off GitHub Actions to third-party runners made jobs 34% faster on average, and switching to tsgo cut the weekly median tsc typecheck by 73%.
- Rewriting lint rules to use static AST analysis instead of the full TypeScript type graph cut API lint time by 68% and full-repository lint time by 55%.
- Batching seven small independent checks into two jobs saved roughly 87,000 runner-minutes a month, 11.8% of total CI usage, based on June figures.
- An opt-in Vitest isolate: false mode that lets safe test files share a module registry was the single largest improvement, worth roughly 17% in monthly savings, but carried the highest correctness risk.
Why it matters
AI coding agents let developers produce and ship code far faster than a team's CI pipeline can validate it. When shipping speed outruns verification speed, the bottleneck shifts from writing code to checking it, and it shows up as both longer waits for developers and agents and rising infrastructure spend as pull request volume and test-suite size grow. Linear treats this as a systemic problem that needs ongoing engineering rather than a one-off fix, and its own numbers show the imbalance is real: a test suite that nearly quadrupled in size over months.
Who it affects
Engineering teams running CI on a growing codebase, especially ones that have adopted AI coding agents and see commit and pull request volume multiply as a result. The specific fixes are most directly relevant to teams using GitHub Actions, a TypeScript toolchain (tsc, ESLint, Vitest), and a pnpm-managed monorepo, since Linear's changes target each of those by name, but the underlying categories (infrastructure, gating jobs, setup cost, test sharding) generalize across languages and toolchains.
How to use it
The post lays out concrete, individually adoptable techniques: move to faster third-party CI runners; switch TypeScript typechecking to tsgo; rewrite lint rules to avoid needing the full type graph, which also eases a move to Oxlint; cap git fetch depth or skip checkout entirely in jobs that don't need a working tree; wrap checkout in retries with backoff and a low-speed timeout; move writes that don't gate anything off the critical path; restrict package installs to only what each job needs; replace full database migration replay with a schema snapshot; batch several short independent checks into fewer jobs; and only add more test shards once per-shard setup cost is low, since setup cost multiplies with shard count. Vitest's isolate: false option, used file by file with explicit opt-in, is offered as a way to cut per-test overhead where state isolation is not needed.
How solid is it
This is Linear's own engineering blog post, not third-party reporting, and it backs nearly every claim with specific before/after numbers (percentages, seconds, minutes, and a monthly runner-minute total tied to June usage). The figures are self-reported and not independently audited. Some comparisons are explicitly narrow, such as "34% faster" being measured over just the two days either side of the runner switch rather than a longer controlled study, and several results (like the 8-shard benchmark) are described as initial or measured a week after the change.
Risks and caveats
The team itself flags the Vitest isolate: false change as carrying the highest correctness risk, since letting test files share a module registry can leak state between them; they required an explicit per-file opt-in comment and added teardown for shared state, and kept files using fake timers or unsafe shared state in the isolated project. Because agents now write most of Linear's tests, the team also updated its agent skills so generated tests follow the same isolation constraints by default. The post does not name the third-party runner provider it switched to, does not give a total dollar figure for cost savings, and does not say how many engineers worked on the rework or over what exact timeframe.
“Agents have made it exponentially faster to ship code, but validating those changes hasn't quite kept up at the same rate.”
— the post's author, a Linear engineer