tsrs is a Rust port of Microsoft's TypeScript 7 compiler that type-checks the same code with the same errors, roughly 4x to 12x faster and with 4x to 7x less memory than the official Go compiler at equal thread counts. It is real, measured, and worth testing in CI today, but it is still a weeks-old community project, and a large share of its speed comes from optimization work rather than from Rust alone.
By Max Wells, updated October 21, 2026
TL;DR: On October 20, 2026, Cloudflare announced tsrs, a function-by-function Rust port of
tsgo, the Go-based TypeScript 7 compiler. Max Schwenk at Owner built it with AI coding agents, then handed it to the Oxc team behind Oxlint and Rolldown. The repository reports 13,458 of 13,462 upstream error baselines matching and a 4.37x geometric mean speedup over TypeScript 7.0.2 when both use 4 checker threads.
- What it is: a drop-in TypeScript 7 compiler and language server written in Rust, not a TypeScript fork
- Headline result: Owner's 37,000-file monolith went from about 80 seconds to about 7 seconds in CI, per Max Schwenk
- The catch: Microsoft's own TypeScript 7.1 is closing part of the gap, partly with ideas found in tsrs
- Verdict: run it as an extra CI job next to
tsc, not as your only type checker yet
What Is tsrs?
tsrs is a faithful Rust translation of the TypeScript 7 compiler, CLI, and language server, built to produce byte-identical output to Microsoft's Go implementation. It does not change the TypeScript language. You keep writing TypeScript, and tsrs replaces the binary that parses, type-checks, and emits it.
The project follows a strict rule written in its porting guide: behavior that matches the Go code is correct, and "improvements" are bugs. Every Go package in microsoft/typescript-go maps to a Rust crate, and every Go file maps to one Rust file. The current port is pinned to upstream commit b85298b6a81f, which corresponds to TypeScript 7.1.0-dev.
Four organizations are involved, and keeping them straight matters for evaluating trust:
| Actor | Role |
|---|---|
| Max Schwenk, Owner | Started the port to fix Owner's slow typecheck, directed the AI agents that wrote it |
| Oxc team (VoidZero), led by Boshen Chen | Current maintainers, repository moved to oxc-project/tsrs |
| Cloudflare | Announced and backs the project, plans WASM and tooling use |
| Microsoft TypeScript team | Owns the language and tsgo; not affiliated with tsrs |
The repository is explicit that tsrs is not affiliated with or endorsed by Microsoft. It is licensed Apache-2.0, ships on npm as tsrs, and runs with npx tsrs. Cloudflare's post adds a line worth quoting directly: "We are not forking TypeScript." The stated goal is a faster implementation of the same language, with the TypeScript team still in control of design.
If you followed Theo Browne's experiment earlier this month, tsrs is the other Rust port. Our analysis of Theo's tsc-rs covers that project. Cloudflare says the two efforts are now merging into one package.
Fact vs Claim: Which tsrs Numbers Hold Up?
The repository's equal-thread benchmarks hold up; several viral numbers do not. The launch produced at least five different speedup figures, and they measure different things.
| Claim | Source | Status | What the evidence says |
|---|---|---|---|
| "Up to 8x faster, ~70% less memory" than TypeScript 7.0 | Cloudflare blog | Attributed, plausible | Repo shows 4.37x geometric mean and up to 11.81x at 4 checkers each |
| 16.87x faster on mui-docs | Repo bench/RESULTS.md | Direct, but unequal | Default settings: tsrs used 16 checkers, tsgo used 4 |
| 18x faster on VS Code | Secondary blog coverage | Not supported | Repo reports 13.55x at defaults and 4.95x at equal threads |
| TypeScript 7.1 beta is "up to 2.5x" faster than 7.0 | Cloudflare blog | Attributed, unconfirmed | Microsoft's own 7.1 beta table peaks at 1.9x |
| tsrs has no watch mode or LSP | Several news summaries | Wrong for native CLI | Only the WASM build lacks them; native --watch works on Linux and macOS |
| 80 seconds to 7 seconds on Owner's monolith | Max Schwenk, Owner | Attributed | 80 s was single-threaded TS 7.0; equal-thread figure is 61.4 s vs 8.75 s |
| 13,458 of 13,462 error baselines match | Repo COMPATIBILITY.md | Direct, self-reported | Remaining four described as test-harness artifacts |
The pattern is consistent. The most honest comparison is tsrs against tsgo with the same number of checker threads, and that comparison is still very strong. The biggest headline numbers come from giving tsrs more threads by default, which is a legitimate product choice but not a language comparison.
How Fast Is tsrs Compared to tsgo?
At equal thread counts, tsrs type-checks large projects about 5x to 12x faster than TypeScript 7.0.2 and uses 4x to 7x less memory on the biggest ones. The repository's benchmark snapshot, dated October 16, 2026, ran 17 open-source projects on a 16 vCPU AMD EPYC machine with 63 GB of RAM, using a PGO build of tsrs.
Selected results with both compilers at --checkers 4:
| Project | tsgo 7.0.2 | tsrs | Speedup | Peak memory (tsgo vs tsrs) |
|---|---|---|---|---|
| mui-docs | 12.69 s | 1.07 s | 11.81x | 7.61 GiB vs 1.05 GiB |
| vscode | 10.94 s | 2.21 s | 4.95x | 7.49 GiB vs 1.80 GiB |
| supabase-studio | 7.24 s | 1.31 s | 5.53x | n/a |
| webpack | 1.46 s | 0.29 s | 5.10x | n/a |
| Geometric mean, 17 projects | 4.37x |
With default settings, tsrs picks more checkers than tsgo. Its default is max(cores / 2, min(cores, 16)), clamped between 4 and 32, while tsgo defaults to 4. On the same machine that produced 16.87x on mui-docs and 13.55x on VS Code. The geometric mean barely moved (4.20x), because small projects cannot use extra threads.
Watch mode is where developers feel it
The incremental numbers are the most interesting part of the benchmark, because they map to every keystroke in an editor. On the VS Code codebase with an 8 vCPU machine:
| Step | tsgo | tsrs | Speedup |
|---|---|---|---|
| Initial build | 12.41 s | 1.86 s | 6.68x |
| First edit (comment change) | 1.76 s | 33 ms | 53x |
| Repeat edit | 1.18 s | 31 ms | 38x |
| Type error in a leaf file | 1.65 s | 34 ms | 48.5x |
| Peak memory | 10.12 GiB | 2.47 GiB | 4.1x less |
Going from more than a second to about 30 milliseconds moves the type checker from "wait for it" to "instant." That is the difference AI coding agents care about too, since an agent loop that type-checks after every edit pays that cost hundreds of times per task.
What about bun check?
The repository also benchmarks bun check from a Bun 1.4.4 canary build, another native TypeScript checker. In a historical 64 vCPU run on VS Code from October 7, tsgo took 9.79 s, Bun 0.87 s, and tsrs 0.53 s. The repository describes tsrs as about 1.9x faster than Bun at equal threads, while using 7% to 25% more memory. The race between native ports is close enough that numbers will keep moving.
Why Did a Rust Port Beat the Official Go Compiler?
Rust did not win on raw language speed; it won because it let the porters control memory layout and object lifetimes that the Go port deliberately left untouched. Understanding Microsoft's original reasoning makes this clearer.
In March 2025, TypeScript lead Ryan Cavanaugh explained why the team picked Go. The key point was that TypeScript 7 was a port, not a rewrite. Go's structure is close to the existing JavaScript codebase, so code could be translated almost line by line. Go also gave enough control over memory layout, and Cavanaugh noted that "batch compilations can effectively forego garbage collection entirely." He implied Rust suited ground-up rewrites, not faithful ports. He also admitted a weakness: Go's in-process JavaScript interop story "is not as good as some of its alternatives."
tsrs tests that reasoning from the other side. It is also a faithful port, and it also copies the architecture function by function. The difference is what Rust exposed once the port worked. Max Schwenk describes the Go compiler's memory as millions of small garbage-collected objects. In Rust, he could choose the size and lifetime of each object. His first Rust build was faster than Go but used more memory. The large wins came after.
The optimizations reported in Schwenk's post, each landed only if it improved instructions by 1%, wall time by 2%, or memory by 5% with byte-identical output:
| Optimization | Reported effect |
|---|---|
| Lazy JSDoc parsing | 21% less memory |
| Lazy member resolution | 23% less memory, 13% less time |
| Smaller struct layouts | 21% less memory, 14% less time |
| Pointer compression (32-bit handles) | 14% to 15% less memory |
| Freeing leaf files after checking | 13% to 16% less memory |
| Memoization | 7% to 12% faster |
| Work stealing between checkers | 13.8% less wall time at 4 checkers, 17% at 8 |
| Profile-guided optimization | 13.5% fewer instructions |
Several of these could be done in Go. That is exactly what TypeScript's Daniel Rosenwasser said on Hacker News: the team ran "our own Rust vibe port," and suspects "a lot of the speed does not just come down to language choice." He added that some of what makes TypeScript 7.1 faster and leaner "actually comes from optimizations discovered in tsrs." In a second comment, he explained that the Go port originally avoided reorganizing data structures to keep porting simple, and that the team now has more flexibility.
So the honest answer has two halves. Rust made layout tricks like 32-bit handles and arena lifetimes natural and safe enough to try quickly. Go remains capable of many of the same algorithmic wins, and Microsoft is now adopting them. For the broader language trade-off, our Rust vs Go comparison covers where each one usually wins.
Inside the Port: Go Packages, Rust Crates, and Arenas
tsrs avoids Rust's borrow checker friction by putting the whole compiler's data in arenas and passing 32-bit handles instead of references. That design is what made a mechanical port of garbage-collected Go code possible.
microsoft/typescript-go (Go) oxc-project/tsrs (Rust, 37 crates)
---------------------------- ---------------------------------
internal/ast/*.go ------> tsrs_ast/src/*.rs (1 file : 1 file)
internal/checker/*.go ------> tsrs_checker/src/*.rs
internal/ls/*.go ------> tsrs_ls/src/*.rs
... tsrs_core <- unsafe kept here (plus generated AST)
tsrs_wasm <- wasm32-wasip1 build
memory model
------------
arena [ node | node | symbol | type | ... ] freed per file or at exit
^
P<T> = 32-bit index into arena (p.get() -> &'static T)
checking
--------
N checker threads (512 MB stack each)
| work stealing between checkers
v
diagnostics sorted -> same output regardless of schedulingAccording to the project's Rust design notes, P<T> is a compressed 32-bit handle, and dereferencing it returns a &'static T. There are no lifetime parameters anywhere in the codebase. P<T> is declared Send and Sync "by decree," interior mutability goes through custom cell types, and the porting rules forbid unsafe outside tsrs_core and generated AST code without a very good reason. Every unsafe block must state its invariant in a // SAFETY: comment, the 31 manual Send/Sync impls are tracked in a reviewed list, and the arena free-list code runs under Miri in CI.
This is a pragmatic trade. Garbage-collected graph structures, like a type checker's symbol tables, are the classic place where idiomatic Rust ownership fights you. Our guide to Rust ownership and borrowing explains why. tsrs sidesteps that fight by making the arena own everything and treating handles as plain integers. The cost is that the compiler's safety rests on the arena's invariants instead of on the type system, which is the main point critics raise.
Determinism got the same attention. Work stealing means files can be checked in different orders, so tsrs sorts output to make it order-independent. Flags --checkerAssignment go and --noLazyMembers reproduce tsgo's behavior exactly for debugging. As Schwenk put it: "A compiler whose errors depend on thread scheduling is a random number generator with opinions."
How Did AI Agents Build a Compiler Port?
Max Schwenk says he "wrote zero code": Claude agents translated the compiler crate by crate, and his job was designing the measurement loop. The details are more useful than the headline.
Owner's monolith, called Olympus, has about 37,000 TypeScript files. A single-threaded TypeScript 7.0 check took 80 seconds and 19 GiB of memory. With linting and language servers running, total usage passed 50 GiB, so a 36 GiB MacBook could not run several coding agents in parallel. That was the business problem.
The process, as described in Schwenk's post:
- Run more than 20 parallel Claude subagents, each owning one crate in its own worktree.
- Get a first working checker from an overnight run.
- Use the upstream test suite as the oracle: 78% of baselines were byte-identical on the first run, later 99.97% of 13,462.
- Accept a performance change only if it beats a fixed threshold with byte-identical output.
His summary of where humans still mattered: "Claude was good at coming up with experiments. Measuring them was the hard part." On Olympus, with tsrs 0.14.0, the results were:
| Compiler | Checkers | Time | Memory |
|---|---|---|---|
| tsgo 7.0.2 | 4 | 61.4 s | 36.0 GiB |
| tsgo 7.1 nightly | 4 | 43.4 s | 28.8 GiB |
| tsrs | 4 | 8.75 s | 6.1 GiB |
| tsrs (default) | 16 | 4.24 s | 9.5 GiB |
Schwenk projects savings of "hundreds of thousands of dollars a year" for Owner. That is a company estimate, not an audited number. The cost of the agent runs themselves was not disclosed.
This is the second strong signal this year that a huge, well-tested codebase plus a mechanical porting rule is where agents perform best. We saw a similar pattern in GitHub's Copilot runtime rewrite in Rust. The test suite does the reviewing that a human would otherwise have to do.
Why Cloudflare and Oxc Care: WASM, Oxlint, and One Toolchain
Cloudflare wants a TypeScript checker that runs in WebAssembly and plugs into Rust tooling, and Go is a poor fit for both. Compiling Go to WASM means bundling Go's garbage collector into every module. Rust has a simpler memory model between the WASM guest and its host.
The @tsrs/wasm package targets wasm32-wasip1. It is single-threaded, capped at 4 GiB of linear memory, and has no watch mode, LSP, or API server. You can try it in the tsrs playground. For a platform where more than 10 million developers build, per Cloudflare, an embeddable checker opens type checking at the edge and in browser-based editors. Our article on how Cloudflare uses Rust covers why the company keeps betting on it.
The Oxc team has a different reason. Oxlint is a fast Rust linter, but type-aware lint rules need a type checker. Today that means calling out to TypeScript. With tsrs as a Rust library in the same ecosystem as Oxlint, Rolldown, Oxfmt, and Vite, type-aware rules can live in one process. Cloudflare lists this as a planned direction, along with merging tsrs and Theo's tsc-rs into one package focused on LSP and content mappers.
Keeping up with Microsoft is the long-term risk. Cloudflare says it will sync upstream with agents, using the same process it runs for Vinext against Next.js: daily upstream review plus a nightly compatibility matrix. Known differences, like diagnostic print order in some cases, are documented.
3 spots open this month → Check if you are eligible.
We help experienced developers transition into Rust roles at €80K–€150K+ in Europe or $130K–$200K+ in the US.
The Skeptical Case Against tsrs
The serious objections are about soundness, benchmark baselines, and long-term maintenance, not about whether the speedups are real. Each deserves a direct answer.
"The unsafe design is unsound." On Hacker News, one commenter argued that tsrs hides unsafe behind an abstraction, so "the LLM/human is doing the proving." This is a fair description. Handles that return &'static T and types declared thread-safe by fiat are not checked by the compiler. The mitigations are real but partial: unsafe is concentrated in one core crate with documented invariants, Miri checks the arena free-list code, and thousands of upstream baselines act as behavioral tests. In practice, a type checker runs on your own trusted code, so the main risk of a hidden memory bug is a crash or a wrong diagnostic in CI, which is another reason to keep the official compiler as the gate.
"The baseline is unfair." Partly true. The repository benchmark compares tsrs (tracking 7.1-dev) against [email protected]. Error differences on 8 of 17 projects disappear when using a 7.1 nightly, which reports exactly what tsrs reports. Microsoft's 7.1 beta improves mui-docs by 1.9x and cuts its memory by 49.6%, so the real gap against 7.1 is smaller than against 7.0. One Hacker News user measured about 4x versus TypeScript 7.0 and 3x versus 7.1 on VS Code.
"It is not just Rust." Correct, and the project does not hide it. Rosenwasser's comments and the optimization table show that algorithmic laziness and layout work produced much of the gain. That is a reason to credit the engineering, not to dismiss the result.
"Known bugs exist." At 16 checkers, drizzle-orm reports the same error count but different locations, and the repository labels it a tsrs bug. LSP coverage is 4,074 of 4,546 fourslash test groups, about 90%. Content mappers work in the CLI but not the LSP.
"Who maintains it in two years?" Pull requests are currently closed for review bandwidth. The project is weeks old, its benchmark CI is disabled, and it depends on tracking a moving upstream. Cloudflare and the Oxc team are credible owners, but this is still a bet on them, not on Microsoft. Our framework for deciding whether to rewrite in Rust applies here too: a fast port only stays valuable if someone keeps paying the maintenance cost.
Should Your Team Use tsrs Today?
Yes as a second type checker in CI or in local agent loops; not yet as the only gate before production. The evidence supports controlled adoption.
Current limits to check first:
- Prebuilt binaries cover macOS arm64 and Linux x64 and arm64 (glibc and musl). There is no Windows or Intel Mac binary yet.
--watchis not supported on Windows.--init,--showConfig,--generateTrace, and localized messages are not supported.--buildpasses 189 of 192 upstream baselines.- Releases move fast: 0.16.0, 0.17.0, and 0.18.0 shipped between October 16 and 19, and the npm scope changed from
@ts-rsto@tsrs.
A practical rollout:
week 1 add "tsrs --noEmit" as a non-blocking CI job next to "tsc --noEmit"
pin exact tsrs version, diff both outputs on every run
week 2+ if diagnostics match for 2 weeks, make tsrs the fast feedback job
keep tsgo as the blocking gate before merge
later use tsrs in local agent loops and watch mode where latency matters
re-evaluate when TypeScript 7.1 stable ships (targeted Nov 24, 2026)Flavio Copes, who tested the WASM build, gave similar advice: a port that passes a large upstream test suite is "useful evidence," and a separate CI job is the right first step. Teams with large monorepos and memory-starved laptops get the most from it. A small project that type-checks in two seconds gains little.
What tsrs Means for Rust and TypeScript Engineers
tsrs is more evidence that JavaScript tooling is moving to native code, and that Rust owns the part of that shift where memory control and WASM matter. The pattern is now broad: SWC, Rspack, Biome, Oxc, Rolldown, Turbopack, and now a type checker.
For TypeScript developers, nothing in your code changes. What changes is the toolchain underneath you. Debugging a slow build, contributing a lint rule, or embedding a checker increasingly means reading Rust. That is a practical reason many TypeScript backend developers are learning Rust without abandoning TypeScript.
For Rust developers, tsrs is a useful case study in arenas, compressed handles, PGO, and deterministic parallelism under real constraints. Those are the skills that separate application Rust from systems and tooling Rust. Teams building developer infrastructure, like the ones behind Oxc, Rolldown, and Cloudflare's tooling, rely on exactly that profile. Our Rust vs TypeScript comparison covers how the two languages split work in a modern stack.
Frequently Asked Questions
tsrs is a Rust port of Microsoft's TypeScript 7 compiler and language server, maintained by the Oxc team under oxc-project/tsrs and announced by Cloudflare on October 20, 2026. It reproduces the Go-based tsgo compiler function by function and targets byte-identical diagnostics. It is not affiliated with Microsoft and does not change the TypeScript language.
Yes, tsrs is about 4.4x faster than TypeScript 7.0.2 on average and up to 11.8x faster on large projects when both use 4 checker threads, per the repository's 17-project benchmark. With default settings it uses more threads and reaches 13x to 17x on some repositories. Incremental watch-mode edits on VS Code drop from over a second to about 33 milliseconds.
Rust let the porters control memory layout and object lifetimes with arenas and 32-bit handles, which cut memory by 4x to 7x on large projects. Cloudflare also wanted a WebAssembly build, and Go's WASM output must bundle its garbage collector. Microsoft chose Go in 2025 because it made a faithful port easier, and its team says much of tsrs's gain comes from optimizations, not language alone.
Not as a sole replacement yet, but it is ready for evaluation. The repository reports 13,458 of 13,462 upstream error baselines matching and all 12,779 type and symbol baselines passing, yet LSP coverage is about 90%, there is no Windows binary, and the project is only weeks old. The safest path is a non-blocking CI job next to the official compiler.
No, the repository states that tsrs is not affiliated with or endorsed by Microsoft. TypeScript's Daniel Rosenwasser did comment publicly that some TypeScript 7.1 performance gains come from optimizations discovered in tsrs. Cloudflare says it is not forking TypeScript and that the TypeScript team should remain in control of the language.
Both are Rust ports of TypeScript 7, but tsrs started at Owner and is now maintained by the Oxc team, while tsc-rs came from Theo Browne's ts-rust experiment. Cloudflare announced that the two projects are merging into one package focused on the compiler, LSP, and content mappers. Theo was reported as saying tsrs was faster than his port in most cases.
Largely, yes. Max Schwenk, Head of AI Developer Experience at Owner, says he "wrote zero code" and used more than 20 parallel Claude subagents, one per crate. The human work was designing the porting rules, the conformance oracle, and the performance measurement thresholds that each change had to pass.
Yes, the native tsrs CLI supports --watch on Linux and macOS and ships a language server, contrary to several news summaries. The WebAssembly build, @tsrs/wasm, is the version without watch mode, LSP, or an API server. Watch mode is not supported on Windows yet.
Bottom Line
tsrs is the strongest evidence yet that a native TypeScript type checker can be dramatically faster than the official one without changing a single diagnostic. The equal-thread numbers, roughly 4x to 12x faster with a fraction of the memory, survive scrutiny. The viral 18x figure and the "no LSP" claims do not.
The more important lesson is about where the speed came from. Rust made aggressive memory layout and lifetime control practical, AI agents made the mechanical port cheap, and a huge upstream test suite made the result trustworthy. Microsoft is already absorbing some of those optimizations into TypeScript 7.1. Test tsrs in CI now, keep the official compiler as your gate, and revisit when TypeScript 7.1 ships.
Related Rustify Articles
- Theo's tsc-rs: TypeScript Compiler in Rust
- Rust at Cloudflare
- Rust vs Go in 2026
- Should You Rewrite It in Rust?
- From TypeScript Backend Developer to Rust
Sources
- Cloudflare, TypeScript, now in Rust, October 20, 2026
- oxc-project, tsrs repository, including
docs/COMPATIBILITY.md,docs/STATUS.md,docs/PORTING.md, anddocs/RUST.md - oxc-project, tsrs benchmark results, snapshot dated October 16, 2026
- Max Schwenk, Owner, tsrs, October 19, 2026
- Daniel Rosenwasser, Microsoft, Announcing TypeScript 7.1 Beta, October 20, 2026
- Ryan Cavanaugh, Microsoft, Why Go?, March 5, 2025
- npm, @tsrs/wasm
- Flavio Copes, tsrs, October 20, 2026
- Paul Sawers, The New Stack, Cloudflare's Rust port of TypeScript, October 20, 2026
- Hacker News, discussion thread, including comments by Daniel Rosenwasser of the TypeScript team












