---
title: "Rust vs Go"
slug: "rust-vs-go"
category: "comparisons"
tags: ["comparisons", "rust", "go", "language", "backend", "performance"]
status: "stable"
last_updated: 2026-05-14
summary: "Pick Rust for performance-critical systems and memory safety without GC pauses; pick Go for microservices and CLIs where simplicity and team ramp matter more."
related: ["[[coding/general-principles]]", "[[coding/testing]]", "[[backend/observability]]", "[[comparisons/python-vs-typescript]]", "[[backend/postgres]]", "[[file-organization/large-codebase]]", "[[ops/cloudflare-workers]]"]
---

## Overview

Pick Rust when the workload is performance-critical, latency-sensitive, or runs in environments that cannot afford a garbage collector: databases, browsers, codecs, embedded, CLI tools meant to be fast for decades. Pick Go when the workload is a microservice, a CLI, or an infrastructure tool where compile speed, runtime simplicity, and team ramp dominate. The 2026 split: Rust owns the cold metal; Go owns the warm metal. A two-language shop is normal; a one-language shop that crosses both domains usually regrets the pick.

## When Rust wins

Rust is the right pick anywhere a memory bug or a GC pause is a production incident.

- Zero-cost abstractions: iterators, traits, and generics compile to code as tight as hand-written C. Go's interface dispatch is cheap but not free.
- Memory safety without GC: the borrow checker eliminates use-after-free and data races at compile time. Go relies on the runtime; Rust eliminates the class.
- Embedded and WASM: `no_std` Rust runs on microcontrollers and ships small WASM binaries (50 to 200 KB) that Go cannot match (1 MB plus).
- Database and infrastructure cores: TiKV, Polars, ScyllaDB, Cloudflare's edge runtime, Astral's uv and Ruff all pick Rust for tail latency.
- Async-await with Tokio is the most mature async runtime outside of Erlang. Go's goroutines are simpler but you cannot tune them.
- LLM agents grounded by `cargo check` produce strong refactors; the compiler is unusually loud. See [[coding/testing]].

## When Go wins

Go is the right pick when the team needs to ship a service in a week and keep shipping for years.

- Compile speed: a 200k-line Go binary builds in 10 seconds. The Rust equivalent takes 5 to 15 minutes cold.
- Learning curve: a new engineer reads Go fluently in a week. Rust takes one to three months to stop fighting the borrow checker.
- Standard library: net/http, encoding/json, database/sql, log/slog all in the box. Rust composes from crates; the equivalent stack is `axum + serde + sqlx + tracing` plus version coordination.
- Goroutines: green threads with a friendly API. Spawning 100k of them is normal; tuning them rarely matters.
- Operational simplicity: a single static binary, no async runtime to configure, GC tuning that almost nobody touches.
- Hiring pool: the Kubernetes ecosystem is Go; the infrastructure-engineering pool defaults to Go fluency.

## Trade-offs at a glance

| Dimension          | Rust                            | Go                                  |
| ------------------ | ------------------------------- | ----------------------------------- |
| Performance        | C-class, predictable tail       | Strong, with GC pauses (low ms)     |
| Memory model       | Borrow checker, no GC           | Garbage-collected                   |
| Compile time       | Slow (minutes)                  | Fast (seconds)                      |
| Binary size        | 1 to 5 MB stripped              | 5 to 15 MB stripped                 |
| Async              | Tokio, async-std, smol          | Goroutines, built-in scheduler      |
| Error handling     | `Result<T, E>` plus `?`         | Multiple return plus `if err != nil`|
| Generics           | Mature, monomorphized           | Mature since 1.18                   |
| Learning curve     | One to three months             | One week                            |
| Tooling            | `cargo`, Clippy, rustup         | `go`, `gofmt`, `go vet`             |
| Ecosystem fit      | Systems, embedded, WASM, edge   | Microservices, CLIs, K8s, infra     |
| LLM agent output   | Compiler grounds strongly       | Friendly to agents; less guard rail |
| Refactor cost      | Compiler catches most breaks    | Tests do most of the work           |

## Migration cost

Cross-language ports cost real money. The common move is to keep both and split by component.

- Go service that hit a tail-latency wall: rewrite the hot path in Rust as a sidecar or library, keep the service shell in Go. Plan one to three engineer-months per hot path.
- Rust service that the team cannot maintain: rewrite in Go. Plan three to nine engineer-months for a 30k-LoC service. Most of the cost is recovering the Tokio-shaped invariants the borrow checker enforced for free.
- New work: pick once, per service, per workload. Rust for the core; Go for the API in front of it is a common stable split.
- Shared protocols: Protobuf, gRPC, or OpenAPI for cross-service contracts. Both languages have first-class support.

## Recommendation

- Database, codec, browser engine, edge runtime, embedded: Rust. See [[ops/cloudflare-workers]] for an edge target.
- Microservice with simple business logic and CRUD over Postgres: Go. See [[backend/postgres]].
- CLI tool you want to ship as a single fast binary: Rust if performance matters; Go if compile speed and contributor velocity matter.
- Kubernetes operator, infrastructure controller, devops glue: Go; the ecosystem is there.
- WASM target for edge or browser: Rust; smaller bundles, predictable runtime.
- Two-language shop: pick Rust and Go; the overlap is small, the strengths are complementary.

## Related

- [[coding/general-principles]]
- [[coding/testing]]
- [[backend/observability]]
- [[comparisons/python-vs-typescript]]
- [[file-organization/large-codebase]]
- [[ops/cloudflare-workers]]
