---
title: "TypeScript 7 Is 10x Faster. Your Builds Aren't."
date: 2026-05-27
type: post
tags: [build-systems, typescript, tsgo, rage, distributed-builds]
summary: "tsgo is 10x faster on one machine. But builds don't run on one machine. The bottleneck just moved, and it moved toward the harness."
---

TypeScript 7.0 Beta [shipped April 21, 2026](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/). The compiler is now written in Go. The numbers are not incremental improvements. They are a category shift.

On the TypeScript compiler itself (~400k lines of TypeScript), tsgo runs 10.8x faster overall, type-checks 30x faster, and uses 2.9x less memory. Sentry's codebase drops from 133 seconds to 16. Editor startup goes from 9.6 seconds to 1.2. Bloomberg, Canva, Figma, Google, Slack, and Vercel are already running it against production codebases. This is not a preview. It is a working compiler with [real receipts](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/).

The natural conclusion: build tooling matters less now. If type checking is 10x faster, why invest in distributed build infrastructure?

That conclusion is backwards. The build harness matters more now, not less.

## The wall that `builders` hits

tsgo's `--builders` flag runs type checking in parallel across Go goroutines on a single machine. Goroutines share memory. The type graph lives in shared address space, so coordination is cheap. There is nothing to serialize.

Cross-machine, all of that disappears.

You cannot share Go's in-process type graph between two machines. It is enormous. It is not designed for serialization. It changes constantly during a check run. Sending it over the wire is not "hard." It is architecturally incompatible with how tsgo works.

Type checking is not embarrassingly parallel. A file's types depend on every file it imports, transitively. On one machine, tsgo resolves those transitive dependencies through shared memory pointers. Across machines, you would need to serialize the type state, transfer it, reconstruct it on the other side, and do this for every file whose imports cross a machine boundary. The cost is not "some network latency." It is a fundamental mismatch between tsgo's execution model and the realities of distribution.

tsgo solves single-machine type checking. It does not solve distributed type checking. The bottleneck just moved.

## The package boundary as the distribution contract

The answer is not to distribute files. It is to distribute packages.

Each package in a monorepo has a public type surface: its `.d.ts` output. When package A depends on package B, A only needs B's `.d.ts` to type-check against. Not B's source files, not B's internal type graph, not the transitive closure of B's dependencies. Just the declaration file that describes the public interface.

This is the inter-machine type contract. The harness resolves the package DAG, type-checks packages in topological order across workers, and ships `.d.ts` artifacts between them. Each worker runs tsgo locally (fast, parallel, shared-memory) and produces a `.d.ts` that the next worker can consume.

Two compiler flags make this clean. `isolatedModules` ensures every file can be type-checked and emitted independently, without resolving types from other files at check time. `isolatedDeclarations` ensures each package can produce its `.d.ts` without deeply resolving its dependencies' internals.

Without these flags, the package's type surface leaks internal details that require the full source of every dependency to resolve. With them, the `.d.ts` is self-contained. The package boundary becomes a clean distribution boundary.

## The parallelism stack

Parallelism compounds across three levels. Each multiplies.

<div class="breakout">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 420" role="img" aria-label="Diagram: The Parallelism Stack showing three compounding levels of parallelism: per-file, per-package, and per-machine">
  <rect width="840" height="420" fill="#F5F0E8" rx="4"/>
  <text x="420" y="32" text-anchor="middle" font-family="Inter, sans-serif" font-size="15" font-weight="600" fill="#2B2421" letter-spacing="0.03em">THE PARALLELISM STACK</text>
  <rect x="60" y="56" width="480" height="80" rx="4" fill="#fff" stroke="#2B2421" stroke-width="1.5"/>
  <text x="80" y="80" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421" letter-spacing="0.04em">LEVEL 1: PER-FILE</text>
  <text x="80" y="100" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">tsgo + isolatedModules. Each file checked independently.</text>
  <text x="80" y="118" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">Go goroutines, shared memory, single machine.</text>
  <rect x="560" y="72" width="100" height="48" rx="4" fill="#A0522D"/>
  <text x="610" y="98" text-anchor="middle" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#F5F0E8">10x</text>
  <text x="610" y="112" text-anchor="middle" font-family="Inter, sans-serif" font-size="10" fill="#F5F0E8">tsgo provides</text>
  <text x="690" y="100" font-family="Inter, sans-serif" font-size="24" fill="#2B2421" font-weight="300">&times;</text>
  <rect x="60" y="156" width="480" height="80" rx="4" fill="#fff" stroke="#2B2421" stroke-width="1.5"/>
  <text x="80" y="180" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421" letter-spacing="0.04em">LEVEL 2: PER-PACKAGE</text>
  <text x="80" y="200" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">DAG ordering. Independent branches run in parallel.</text>
  <text x="80" y="218" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">200 packages, 5-hop critical path = 40 concurrent.</text>
  <rect x="560" y="172" width="100" height="48" rx="4" fill="#6B5F55"/>
  <text x="610" y="198" text-anchor="middle" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#F5F0E8">Nx</text>
  <text x="610" y="212" text-anchor="middle" font-family="Inter, sans-serif" font-size="10" fill="#F5F0E8">harness provides</text>
  <text x="690" y="200" font-family="Inter, sans-serif" font-size="24" fill="#2B2421" font-weight="300">&times;</text>
  <rect x="60" y="256" width="480" height="80" rx="4" fill="#fff" stroke="#2B2421" stroke-width="1.5"/>
  <text x="80" y="280" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421" letter-spacing="0.04em">LEVEL 3: PER-MACHINE</text>
  <text x="80" y="300" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">Distributed execution. DAG shards across build workers.</text>
  <text x="80" y="318" font-family="Source Serif 4, Georgia, serif" font-size="13" fill="#6B5F55">Ship .d.ts artifacts between machines. Nothing else.</text>
  <rect x="560" y="272" width="100" height="48" rx="4" fill="#6B5F55"/>
  <text x="610" y="298" text-anchor="middle" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#F5F0E8">Mx</text>
  <text x="610" y="312" text-anchor="middle" font-family="Inter, sans-serif" font-size="10" fill="#F5F0E8">harness provides</text>
  <line x1="60" y1="360" x2="780" y2="360" stroke="#DDD7CD" stroke-width="1"/>
  <rect x="200" y="372" width="440" height="36" rx="4" fill="#2B2421"/>
  <text x="420" y="396" text-anchor="middle" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="#F5F0E8">Total speedup = 10x &times; Nx &times; Mx</text>
  <line x1="730" y1="72" x2="730" y2="120" stroke="#A0522D" stroke-width="1.5"/>
  <text x="755" y="100" font-family="Inter, sans-serif" font-size="10" fill="#A0522D">tsgo</text>
  <line x1="730" y1="172" x2="730" y2="320" stroke="#6B5F55" stroke-width="1.5"/>
  <text x="755" y="240" font-family="Inter, sans-serif" font-size="10" fill="#6B5F55">harness</text>
</svg>
</div>

**Per-file:** tsgo with `isolatedModules` checks each file independently within a package. This is the 10x that ships today. Gains scale with codebase size: 4x under 10k lines, 8.8x at 100k-500k, roughly 10x at 500k+.

**Per-package:** The harness orders packages by the dependency graph and runs independent branches concurrently. A 200-package monorepo with a critical path of 5 hops means up to 40 packages running at the same time.

**Per-machine:** The harness distributes DAG shards across build workers. Each worker runs tsgo locally. The only inter-machine payload is the `.d.ts` artifact.

The theoretical speedup: **10x (tsgo) &times; package parallelism factor &times; machine count**, bounded only by the critical path through the DAG. Everything off the critical path is pure parallel win.

tsgo gives you the first level. The harness gives you the other two. Without the harness, 10x is the ceiling. With it, the ceiling is much higher.

## The discipline problem

Here's where the story gets structural. The same code discipline that unlocks tsgo's per-file parallelism is the same discipline that unlocks the harness's distributed parallelism. Both require `isolatedModules`. Both break on the same failure mode: files with implicit dependencies on the full type graph.

Teams that built without `isolatedModules` cannot benefit from tsgo's parallelism. Those same teams cannot benefit from distributed execution. The discipline failure blocks both paths simultaneously.

This looks like a people problem. Developers should have enabled `isolatedModules` from day one. They should have known better.

But at the bottom, it's a tooling problem. The tooling never enforced isolation. The default was `isolatedModules: false`. So codebases accumulated implicit full-graph dependencies for years, one file at a time, with no warning.

In the middle, it looks like a people problem. In truth, it's a tooling problem masquerading as a people problem masquerading as a tooling problem.

The answer is a build harness that enforces `isolatedModules` as a build requirement. Not a guideline. Not a recommendation. A gate. Packages that can't satisfy isolation get flagged at configuration time, before they ever reach the build queue.

## What the harness still does

tsgo handles type checking on a single machine. That is one piece. Here is the rest.

<div class="breakout">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 380" role="img" aria-label="Diagram: What tsgo solves vs what it doesn't. tsgo handles single-machine type checking. The harness handles cross-package ordering, distribution, caching, scoping, enforcement, and orchestration.">
  <rect width="840" height="380" fill="#F5F0E8" rx="4"/>
  <text x="210" y="32" text-anchor="middle" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="#2B2421" letter-spacing="0.04em">WHAT tsgo SOLVES</text>
  <rect x="40" y="48" width="340" height="310" rx="4" fill="none" stroke="#DDD7CD" stroke-width="1"/>
  <rect x="60" y="68" width="300" height="44" rx="3" fill="#fff" stroke="#2B2421" stroke-width="1"/>
  <text x="210" y="88" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Single-machine type checking</text>
  <text x="210" y="104" text-anchor="middle" font-family="monospace" font-size="10" fill="#6B5F55">10.8x faster overall</text>
  <rect x="60" y="124" width="300" height="44" rx="3" fill="#fff" stroke="#2B2421" stroke-width="1"/>
  <text x="210" y="144" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Per-file parallelism</text>
  <text x="210" y="160" text-anchor="middle" font-family="monospace" font-size="10" fill="#6B5F55">goroutines + shared memory</text>
  <rect x="60" y="180" width="300" height="44" rx="3" fill="#fff" stroke="#2B2421" stroke-width="1"/>
  <text x="210" y="200" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Memory efficiency</text>
  <text x="210" y="216" text-anchor="middle" font-family="monospace" font-size="10" fill="#6B5F55">2.9x less memory</text>
  <rect x="60" y="236" width="300" height="44" rx="3" fill="#fff" stroke="#2B2421" stroke-width="1"/>
  <text x="210" y="256" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Editor/LSP speed</text>
  <text x="210" y="272" text-anchor="middle" font-family="monospace" font-size="10" fill="#6B5F55">9.6s → 1.2s startup</text>
  <text x="210" y="326" text-anchor="middle" font-family="Source Serif 4, Georgia, serif" font-size="13" font-style="italic" fill="#948880">Solved. Genuinely.</text>
  <text x="630" y="32" text-anchor="middle" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="#2B2421" letter-spacing="0.04em">WHAT THE HARNESS SOLVES</text>
  <rect x="460" y="48" width="340" height="310" rx="4" fill="none" stroke="#A0522D" stroke-width="1.5"/>
  <rect x="480" y="68" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="92" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Cross-package DAG ordering</text>
  <rect x="480" y="114" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="138" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Distributed execution</text>
  <rect x="480" y="160" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="184" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Remote cache (CI → local dev)</text>
  <rect x="480" y="206" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="230" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Change scoping (skip unaffected)</text>
  <rect x="480" y="252" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="276" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">isolatedModules enforcement</text>
  <rect x="480" y="298" width="300" height="36" rx="3" fill="#A0522D" fill-opacity="0.08" stroke="#A0522D" stroke-width="1"/>
  <text x="630" y="322" text-anchor="middle" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#2B2421">Bundling + lint orchestration</text>
  <text x="630" y="356" text-anchor="middle" font-family="Source Serif 4, Georgia, serif" font-size="13" font-style="italic" fill="#A0522D">The bottleneck moved here.</text>
</svg>
</div>

A 10x faster type checker running unscoped across 500 packages is still 50x slower than a scoped run across 10 affected packages. Speed without scoping is waste. And scoping is a harness concern, not a compiler concern.

tsgo makes the type-check step fast. The harness makes the build system intelligent.

## Where the bottleneck lives now

The single-machine type-checking problem is solved. tsgo solved it. Congratulations to the TypeScript team. This is genuinely excellent work.

The remaining bottleneck is coordination: which packages to check, in what order, on which machines, with what cached. That is what a build harness does. tsgo made the harness more important by making everything else fast enough that coordination is the dominant cost.

When type checking was slow, the harness was an optimization. Now that type checking is fast, the harness is the architecture.
