2024-11-19 · meta · ~4 min read

Why Rust, after years of Go

Most of the systems software I'd written before frostvex was in Go. I like Go. Rolled-out tooling, fast compile times, predictable runtime behavior, an ecosystem deep enough to find a maintained library for almost anything. The fact that frostvex is in Rust is a deliberate departure that took me a while to commit to.

This post is the case I made to myself in late 2024. With about a year of frostvex's commit history behind me, I think it still holds up.

The two reasons

Memory model. Frostvex's hot path is lots of small allocations — chunk hashes, manifest entries, peer state. With Go, the GC pauses on a 100k-file pool were measurable. They didn't break anything; they did make the p99 numbers harder to reason about. Rust gives me deterministic allocation and freedom from "wait, is this allocation going to provoke a collection?"

FFI and binary size. I knew I'd want to embed the BLAKE3 reference implementation, which has SIMD intrinsics that you can't easily get to from Go. And I wanted a small static binary — Go binaries are 8–12 MB out of the box, which is fine but not nice. Rust with LTO and stripped symbols clocks in at ~3 MB for frostvex.

Neither of these is a knockout argument. But together, they were enough.

What I gave up

Compile times. Go's go build on the same project would take maybe 4 seconds. Rust's cargo build --release with LTO is 2 minutes. Debug builds are 8 seconds, which is OK, but I miss the Go feedback loop.

Goroutines. Tokio's async story is the closest equivalent and it's pretty good, but the mental model is different — every async function colors its callers. You learn to live with it.

Stdlib breadth. Go's stdlib has, broadly speaking, everything I need to write a network service. Rust's stdlib is smaller, and I lean on third-party crates (tokio, serde, quinn, im, blake3, reed-solomon-erasure). Each of those is a maintenance dependency.

Was it worth it

Tentatively yes. The reasons:

Things I miss: Go's standard library, simple tooling, fast iteration. The honest answer is that "Rust over Go" was the right call for this specific project; for the next project I might pick Go again.


If you've shipped a similar tool in both languages and disagree, I'd love to hear about it.