Why Turborepo Is Moving From Go to Rust

Turborepo, the build system for JavaScript and TypeScript monorepos, is undergoing an incremental migration from Go to Rust, starting with version 1.7. The move is driven by how the project's needs have evolved as it has scaled and merged development efforts with Turbopack.

The original choice of Go followed esbuild's lead: it's fast, avoids Node.js initialization overhead, and offers a developer experience geared toward rapid iteration. Those qualities served Turborepo well early on. But as the codebase grew and the team began sharing more infrastructure with Turbopack, Go's strengths started to misalign with what Turborepo actually needed to do.

Go's strengths don't match the problem

Go is built for network computing in data centers. Its goroutine-per-request model, Context API, and standard library server infrastructure make it excellent for large-scale services. But there's a tradeoff: Go prioritizes simplicity over expressiveness, which means more errors surface at runtime that other languages would catch at compile time.

For a service running in a data center, that tradeoff is acceptable—you can roll back, fix, and redeploy. But for software that users install on their own machines, the cost of those runtime errors is much higher. Turborepo needs up-front correctness, particularly when dealing with process management, filesystems, and other low-level OS concepts.

A concrete example is file permissions. Go lets you set a Unix-style permission code, but that abstraction doesn't carry across platforms—Windows has no equivalent concept. Go will happily allow you to set a permission code on Windows even though it has no effect. In Rust, you must explicitly mark that code as Unix-only; otherwise it won't compile on Windows. That forced explicitness catches problems before they reach users.

Rust aligns with the team's needs

Rust's community has prioritized correctness over API abstraction. That means additional complexity surfaces in the codebase, but it's necessary complexity for the problems Turborepo solves. Rust's type system lets developers encode constraints that are checked at compile time rather than reported as GitHub issues later.

Rust is also the language Turbopack chose from day one. Since both teams share a codebase and work on similar build tooling problems, maintaining parallel implementations in Go and Rust meant solving the same problems twice. Aligning on one language lets both teams share development and maintenance of common utilities—for example, Turborepo is taking inspiration from Turbopack's file-watching approach to build smarter cross-workspace hot reloading.

Another practical benefit: Rust's ecosystem for native library interop is much more contained than Go's. In Go, interfacing with C libraries requires CGO, which forces a global switch from the pure Go toolchain to a much slower C toolchain for the entire codebase. Rust's bindgen and cxx create safe wrappers without global build changes, and many libraries already ship with generated wrappers. For instance, the team ported Turborepo's git interface using the git2 crate, which wraps the C library libgit2 behind a safe, idiomatic Rust API. As Turborepo increasingly relies on native C packages like zstd for cache compression, this difference matters.

Team satisfaction and ecosystem pull

The team also notes that developers simply want to write Rust. That matters for morale and burnout prevention, and Rust's efficiency also means lower energy consumption. Beyond the internal team, Rust has ranked as one of the most-loved languages in StackOverflow surveys for years. Many web developers are looking to Rust as a second language after JavaScript, which lowers the barrier for contributors coming from a JS tooling background and helps the Turbo community grow.

An incremental path forward

The migration isn't a rewrite. Turborepo currently runs what the team calls a "Rust-Go-Rust Sandwich": Rust is the entry point, and each command's implementation can live in either language. Go code can call Rust code as well, via the turborepo-ffi crate and the corresponding ffi.go file. That gives the team flexibility to keep Go where it works while steadily moving functionality into Rust.

Turborepo 1.8 already ships with more features written in Rust, continuing the phased transition that began with 1.7. For teams debating a similar language shift, the core lesson is to weigh a language's priorities against your specific problem domain—not just its general reputation for speed or developer experience.