Skip to content

Build2 publishers3 min readPublished

Capping fetch depth took Linear's slowest CI gate from 94 seconds to 20

Linear rebuilt its CI pipeline after its CTO filed an issue about cost, and the numbers it published show verification volume growing faster than the savings on each test. The largest wall-clock gains came from the jobs that decide what to run.

The Engineer · Build desk

Illustration accompanying Capping fetch depth took Linear's slowest CI gate from 94 seconds to 20

What happened

  • Linear said on September 21st that a CI overhaul ordered by CTO Tuomas Artman cut runner time per test roughly in half even as the test suite nearly quadrupled during 2026.
  • Artman opened the work as an issue titled "CI costs are high" and assigned it to engineer Mufeez Amjad, telling him to make the pipeline faster as well as cheaper.
  • The repository is adding roughly 2,000 tests a week, and Linear says agents now write most of them.
  • Over the two days either side of the move off GitHub Actions to third-party runners with faster CPUs and storage, jobs ran 34% faster on average and tsc workloads 52% faster.
  • After the switch, checkout with actions/checkout slowed and sometimes hung, and the provider traced the stalls to intermittent degradation on the direct IP link the runners use to reach GitHub.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost Each agent attempt now waits a little over five minutes instead of the roughly 11 the grown suite would otherwise need, and agents make far more attempts than people do.
  • constraint The cheapest jobs set the floor on pull request wait, because none of the eight API test shards can start until the change-detection gates finish.
  • decision Anyone copying the list has to check their own gate first: the typecheck and lint wins depended on Linear's toolchain, while Amjad says the gating and checkout work applies across languages.
  • exposure Linear now owns checkout reliability itself, maintaining retry and timeout logic and a persistent Git mirror in place of the action GitHub ships.

Halving the runner time per test does not halve the bill when the suite grows four times bigger [1]. Multiply the two together: four times the tests at about half the machine time each leaves the pipeline consuming roughly twice January's runner minutes [1]. The per-test cost fell and total consumption rose. Linear published the growth as an index against its own January pipeline, not as a test count [9]. At 2,000 tests a week [7] across the roughly 37 weeks to September 21st, about 74,000 tests went in, and for that to be three times the starting suite, January began near 25,000 tests [5].

The minute of wall-clock saving came from in front of the tests. Every run begins by checking which paths the pull request touched and whether those tests have already passed for the same inputs, and Linear gates on the result at the job level so skipped work never reserves a runner [16]. One of those gates decides whether a diff contains a database migration and emits a signal that schedules the database checks [17]. It was checking out the full working tree to answer that, which is thorough [17]. Capping the fetch depth took the slowest of these gates from 94 seconds to 20, jobs that never needed a working tree at all went from 27 seconds to 7, and a sparse, blobless checkout with limited history on push and merge-queue events saved about 11 seconds more [18]. The slowest gate alone shed 74 seconds, against a total pull request wait reduction of roughly one minute [3][4].

What transfers depends on what gates your pipeline. Switching to tsgo cut the weekly median of Linear's tsc check by 73% [11], "large enough to move the bottleneck off of typechecking entirely", Amjad wrote [12]. The lint numbers came out of a specific defect: a handful of custom rules needed TypeScript type information, so every lint run built the full type graph before evaluating them, making linting one of the most memory-intensive jobs in the pipeline [13]. Rewriting those rules to read the syntax tree for function-like constructs and guard patterns let ESLint drop TypeScript entirely, cutting API lint time by 68% and full-repository lint time by 55% [14]. An ESLint config that never loaded the type checker has none of that to win back. These are Linear's internal measurements, not an outside benchmark [9].

Linear groups the work under four headings: upgraded infrastructure and tooling, optimising the jobs that gate other work, reducing repeated setup, and making test execution more efficient [23]. The changes described in detail are the infrastructure swap and the gates. The pressure behind them shows in the product numbers Linear disclosed in August, when it said agents were installed in 95% of its paid workspaces and generated 50% of work in the product, up from 3% a year earlier [21]. Agents write most of Linear's tests now [6]. "Agents have made it exponentially faster to ship code, but validating those changes hasn't quite kept up at the same rate," Amjad wrote [5].

What to watch

  • Whether Linear publishes numbers for the other two areas, reducing repeated setup and test execution, which is where per-test runner time is won.
  • A figure for the runner-minutes Oxlint saved on linting, which Linear described without quantifying.
  • Whether the direct IP link between the third-party runners and GitHub degrades again now that Linear's own retry logic and Git mirror sit in front of it.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories