TL;DR
Rust vs Go for backends comes down to where each one pays for itself. Rust’s performance edge is real but narrow on throughput. It shows up most in tail latency and memory, because Rust has no garbage collector and Go’s GC, by default, lets the heap grow to roughly twice the live data before collecting. Go ships services faster, is used by more professional developers (17.4% vs 14.5% in the 2025 Stack Overflow survey), and powers Kubernetes and most of the cloud-native stack. On the hiring side, a count I ran over five Hacker News “Who is hiring?” threads found Rust mentioned in more posts than Go since October 2025. Use Go for most services where development speed comes first. Use Rust where P99 latency, memory footprint or memory safety is a hard requirement.
Versions, survey figures and hiring counts last verified: October 17, 2026.
Part of our Modern Go in 2026 series: the guide connects this comparison to iterators, generic methods, JSON v2, and the Green Tea GC.
Why Teams Reconsider Go: The Discord Case
Go is the default for a lot of backend services, CLI tools and infrastructure scripts, and most teams that look at Rust do it for the same reason: a hot path where memory or tail latency starts costing real money. The best-known public example is Discord’s Read States service. Its Go version spiked in latency every two minutes as the garbage collector scanned a large in-memory cache, and the Rust rewrite removed the spikes and cut both average and tail latency.
Read this before starting that kind of rewrite. It covers the published evidence on performance, the same endpoint in both languages, and a hiring count you can rerun yourself.
Performance: What the Evidence Shows
Search “Rust vs Go performance” and you’ll find confident numbers everywhere: Rust 12x faster, 5x better P99, 160,000 requests per second on two cores. Most of them trace back to single-author blog posts with no published harness, and they rarely agree with each other. An earlier version of this article repeated two of those figures. I removed them in this October 2026 update after failing to trace them to a benchmark anyone could rerun.
The mechanism holds up better than the numbers. Rust and Go both compile to native code, so on a request that spends most of its time waiting on Postgres or another service, the language runtime is a small slice of the total. The differences show up in three places: CPU-heavy hot loops, the tail of the latency distribution, and memory.
Throughput: framework and workload beat language
On CPU-bound work (parsing, compression, crypto, serialization-heavy endpoints), Rust usually wins because it has no GC and LLVM optimizes aggressively. On a typical CRUD endpoint the gap narrows, because the database round-trip dominates, and framework choice, connection pooling and JSON handling move the numbers more than the language does. On the Go side, the new JSON v2 encoder trims a chunk of serialization cost without a rewrite.
If raw throughput is the deciding factor, benchmark your own handler on your own hardware. A 50-line prototype in each language tells you more than any published leaderboard.
Tail latency: the garbage collector
The garbage collector is the main source of tail latency in Go services. Go’s GC guide is upfront about it: the collector “is not fully stop-the-world and does most of its work concurrently with the application”, but it still adds latency through brief stop-the-world pauses between the mark and sweep phases, through taking 25% of CPU during the mark phase, and through GC assists, where goroutines that allocate heavily are made to help with marking.
Discord’s case shows how that plays out with a large heap. Read States kept an LRU cache holding tens of millions of entries. The service made very little garbage, but, as the Discord team found by reading the Go source, “Go will force a garbage collection run every 2 minutes at minimum.” Each forced run scanned the entire cache and produced a latency spike. They tried Go 1.8, 1.9 and 1.10 without improvement. The Rust version, after some tuning, “beat Go on every single performance metric”: latency, CPU and memory.
The case is from February 2020 and Go 1.9.2. Go has since added a soft memory limit (GOMEMLIMIT, Go 1.19) and made the Green Tea collector the default in Go 1.26, which the Go team expects to cut GC overhead by 10–40% in programs that lean heavily on the collector. And most REST APIs never hold a heap like that. For a typical service serving web and mobile clients, Go’s P99 is fine. For ad-tech bidding, real-time game servers or trading systems, tail latency is usually the main requirement.
Memory: the GOGC math
The memory gap has a simple mechanical explanation. Go’s GC guide gives the formula for when the next collection starts:
Target heap memory = Live heap + (Live heap + GC roots) * GOGC / 100
With the default GOGC=100, the heap is allowed to grow to roughly twice the live data before the collector runs. A Rust service frees memory the moment the owning value goes out of scope, so its peak sits much closer to the live set. Here’s what that means at fleet scale, calculated from the formula above with an illustrative 120 MB live heap:
live_mb = 120 # live data per pod, same in both languages
roots_mb = 5 # goroutine stacks + globals (Go only)
pods = 12 * 3 # 12 replicas x 3 availability zones
go_peak = live_mb + (live_mb + roots_mb) * 100 / 100 # GOGC=100
rust_peak = live_mb # freed on drop
print(f"Go peak heap per pod: {go_peak:.0f} MB")
print(f"Rust peak heap per pod: {rust_peak:.0f} MB")
print(f"Extra cluster memory for Go: {(go_peak - rust_peak) * pods / 1024:.1f} GB")
Running it prints:
Go peak heap per pod: 245 MB
Rust peak heap per pod: 120 MB
Extra cluster memory for Go: 4.4 GB
This is a model, and real Rust services carry allocator overhead, and a Go service can lower GOGC or set GOMEMLIMIT to trade CPU for memory. But it shows why “Rust uses less memory” holds up in production reports, and why the gap grows with heap size.
The Same API in Both Languages
Here’s a simple JSON API endpoint in both languages, accepting a POST body and returning a response. This is the kind of code that makes up 90% of backend services.
Go (using the standard library):
package main
import (
"encoding/json"
"log"
"net/http"
)
type Item struct {
Name string `json:"name"`
Price float64 `json:"price"`
}
type Response struct {
Status string `json:"status"`
Tax float64 `json:"tax"`
}
func handleCreate(w http.ResponseWriter, r *http.Request) {
var item Item
if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
resp := Response{
Status: "created",
Tax: item.Price * 0.19,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
}
func main() {
http.HandleFunc("/items", handleCreate)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Rust (using Axum):
use axum::{Json, Router, routing::post};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Item {
name: String,
price: f64,
}
#[derive(Serialize)]
struct Response {
status: String,
tax: f64,
}
async fn handle_create(Json(item): Json<Item>) -> Json<Response> {
Json(Response {
status: "created".into(),
tax: item.price * 0.19,
})
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/items", post(handle_create));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
The Go version needs nothing beyond the standard library. The Rust version pulls in tokio, axum and serde, so its first clean build compiles that whole dependency tree before touching your code, which is where Rust’s slow-build reputation comes from. Incremental rebuilds after that are much quicker. Both produce a single binary with no runtime dependencies.
The Rust code is slightly longer. Axum’s extractor pattern (Json(item): Json<Item>) replaces Go’s explicit decode-and-error-check with compile-time type extraction. If the body parses but doesn’t match Item, Axum rejects it automatically with a 422 (400 for malformed JSON, 415 for a missing JSON content type). In Go, you handle that yourself.
Feature Comparison
| Feature | Go 1.27 | Rust 1.99 |
|---|---|---|
| Compilation | Fast; stdlib-only services build in seconds | Slower clean builds (whole dependency tree); fast incremental |
| Binary size | Single static binary, a few MB and up | Single binary, often smaller once stripped; grows with crates |
| Memory model | Garbage collected | Ownership + borrow checker |
| Concurrency | Goroutines + channels | async/await + Tokio |
| Error handling | if err != nil | Result<T, E> + ? operator |
| Generics | Since Go 1.18 (2022); methods too in 1.27 | Since Rust 1.0 (2015) |
| Package manager | go mod (built-in) | Cargo (built-in) |
| Learning curve | Weeks to productive (rough estimate) | Months to productive (rough estimate) |
| Null safety | nil (runtime panics) | Option<T> (compile-time) |
| Cross-compilation | GOOS=linux go build | cargo build --target + linker config |
| IDE support | gopls (excellent) | rust-analyzer (excellent) |
| Standard library | Batteries included (HTTP, JSON, crypto) | Minimal: community crates |
When Go Wins
Cloud-native services and APIs
Go powers Docker and Terraform, and a long list of CNCF graduated projects: Kubernetes, Prometheus, etcd, containerd, Helm and Istio among them. If your service runs on Kubernetes and talks to other services over gRPC or REST, Go is the path of least resistance. The toolchain, the deployment model, and the debugging story all assume Go.
Developer velocity
An experienced Go developer can have a working CRUD service running in an afternoon. The language has 25 keywords. With one formatter (gofmt), one error-handling idiom (if err != nil) and one module system (go mod), a new hire can usually read an unfamiliar Go codebase in their first week.
Rust’s ownership model, lifetime annotations, trait bounds, and macro system give you deep control over memory and type safety, but they slow down the first few months. For a team of 5 building microservices on a quarterly release cycle, Go’s shorter ramp-up is a real advantage.
Hiring and onboarding
More developers already know Go: 17.4% of professional developers in the 2025 Stack Overflow survey said they’d done extensive work in it over the past year, against 14.5% for Rust. Rust interviews also tend to be more involved, with questions about lifetimes, trait objects and async pinning, while Go interviews stick to goroutines, channels and interface design. Someone who’s “pretty good at Go” tends to be useful within days, while someone who’s “pretty good at Rust” usually still needs time with the borrow checker in a production codebase. Demand is a different story, covered in the hiring data below.
CLI tools
Go’s single-binary output, fast compilation, and trivial cross-compilation (GOOS=windows go build) make it the default for developer tooling. Docker CLI, GitHub CLI, Terraform, and Hugo are all Go. Cobra and Bubbletea give you argument parsing and terminal UIs with minimal friction. If you’re starting with Go CLI development, the Go iterators guide covers the iter package that makes data processing pipelines cleaner, and our Go 1.26 tutorial walks through the latest language features including Green Tea GC improvements.
When Rust Wins
Latency-sensitive systems
If your SLA has a P99 target in the low single-digit milliseconds, Go’s garbage collector is a risk factor you have to manage. Rust’s deterministic memory management means no GC pauses, no GC assists and flatter latency curves under load. That’s why some ad-tech bid servers, trading systems and real-time game backends are written in Rust.
Memory-constrained environments
The GOGC math above compounds across a fleet. Multiply the per-pod difference across 20 services in a microservice architecture and you can be looking at extra nodes in the cluster. At scale, the infrastructure savings can justify the longer development cycle, though for Go it’s worth trying GOMEMLIMIT before reaching for a rewrite.
Security-critical code
Rust catches whole classes of memory bugs (buffer overflows, use-after-free, data races) at compile time. Go is memory-safe in normal code (bounds checks, and a GC that prevents use-after-free), but data races, and the memory corruption they can cause, are caught only at runtime by the race detector, and only on code paths that actually execute. Google’s 2025 Rust in Android report puts numbers on the compile-time approach: an estimated 0.2 memory-safety vulnerabilities per million lines of Rust, against a historical figure closer to 1,000 for C and C++, with memory-safety bugs falling below 20% of Android’s vulnerabilities for the first time in 2025. Cloudflare’s Pingora is a good example of why companies pick Rust for this layer: it replaced an NGINX setup written in C and Lua, and Cloudflare reports it uses about 70% less CPU and 67% less memory than the old service at the same traffic load. That comparison is against C and Lua, not Go, but memory safety without a GC was the stated reason for choosing Rust.
Systems software
Operating systems, databases, compilers, browser engines, embedded firmware. For decades C and C++ were the only realistic options here. Rust is now making real inroads, while Go never targeted this space. The Linux kernel has accepted Rust code since 6.1, and Google ships Rust across Android and its own apps, including Nearby Presence, the Bluetooth device-discovery protocol.
Rust vs Go Hiring: What 1,573 HN Job Posts Show
The usual hiring claim is that Go has several times more openings than Rust. That’s hard to check, because LinkedIn and Indeed counts swing with the query and can’t be reproduced, so I counted something anyone can recount. The script below pulls every top-level post from five Hacker News “Who is hiring?” threads through the public Algolia API and counts how many posts mention each language:
import json, re, urllib.parse, urllib.request
API = "https://hn.algolia.com/api/v1"
MONTHS = ["October 2024", "April 2025", "October 2025", "April 2026", "October 2026"]
# "golang" in any case, or capitalised "Go" that isn't "go to"/"Go-To-Market" etc.
GO = re.compile(r"(?i:\bgolang\b)|\bGo\b(?![\s-]+(?i:to|ahead|live|through|beyond|back)\b)")
RUST = re.compile(r"\brust\b", re.IGNORECASE)
def get(url):
req = urllib.request.Request(url, headers={"User-Agent": "danilchenko.dev research"})
with urllib.request.urlopen(req, timeout=60) as r:
return json.load(r)
def thread_id(month):
title = f"Ask HN: Who is hiring? ({month})"
q = urllib.parse.quote(f'"{title}"')
hits = get(f"{API}/search?query={q}&tags=story,author_whoishiring")["hits"]
return next(h["objectID"] for h in hits if h["title"] == title)
print(f"{'thread':<14} {'posts':>5} {'Go':>5} {'Rust':>5} {'Go:Rust':>8}")
for month in MONTHS:
item = get(f"{API}/items/{thread_id(month)}")
posts = [re.sub(r"<[^>]+>", " ", c["text"]) for c in item["children"] if c.get("text")]
go = sum(1 for p in posts if GO.search(p))
rust = sum(1 for p in posts if RUST.search(p))
print(f"{month:<14} {len(posts):>5} {go:>5} {rust:>5} {go / rust:>8.1f}")
The output on October 17, 2026:
| Thread | Job posts | Mention Go | Mention Rust | Go:Rust |
|---|---|---|---|---|
| October 2024 | 329 | 33 | 23 | 1.4 |
| April 2025 | 306 | 29 | 25 | 1.2 |
| October 2025 | 341 | 22 | 25 | 0.9 |
| April 2026 | 331 | 27 | 30 | 0.9 |
| October 2026 | 266 | 18 | 24 | 0.8 |
Two years ago Go appeared in 40% more posts than Rust. Since October 2025, Rust has been ahead in every thread I sampled. The first version of the regex miscounted, so I checked matches by hand: it missed “Golang” with a capital G and counted “Go-To-Market” sales roles as Go jobs. The version above fixes both.
Read the table with its limits in mind. HN hiring threads skew toward US and EU startups and infrastructure companies, which is exactly Rust’s home turf. A post that mentions a language isn’t necessarily hiring for it (“Rust, C/C++, Go, JavaScript” in a stack list counts once for each), and the October 2026 thread was still collecting posts when I ran this. What the numbers do show is that, at least at startups, “Go has far more jobs” no longer holds. Go’s lead is in the existing developer pool and in larger, older companies, not in fresh demand.
On pay, Rust roles are widely reported to carry a premium, and RustJobs.dev’s salary guide is the usual source, but I couldn’t find a reproducible dataset that compares the two languages directly, so I’m not quoting a number. The premium, where it exists, reflects scarcity: fewer experienced Rust developers, hired mostly by fintech, infrastructure and security companies that pay top of market. For broader context on how AI is changing tech compensation, see our tech careers guide. If you’re considering the Cyprus or EU market specifically, the Cyprus developer salary breakdown, the wider Europe developer salary report, and our look at where software engineer jobs in Europe are in 2026 have localized numbers.
For career planning: Go is the faster language to get productive in and the one more teams already run. Rust is the one where startup demand has caught up with Go’s while the pool of experienced developers is still smaller. The pragmatic move is still to learn Go first, then add Rust when your work touches performance-critical paths, but don’t wait as long as the old “Go has 5x the jobs” advice suggested.
Decision Framework
Pick Go when:
- The service is I/O-bound (API gateway, CRUD service, webhook processor)
- The team has mixed experience levels
- You need to ship in weeks, not months
- You need to staff up quickly from a wide pool of backend engineers
- The service will be maintained by people who didn’t write it
Pick Rust when:
- The service is CPU-bound or latency-sensitive (stream processing, video encoding, ML inference serving)
- Memory footprint directly impacts infrastructure cost
- The code handles untrusted input and memory safety is a compliance requirement
- You’re building something that other software depends on (library, runtime, proxy)
- The team has 3+ months to ramp up and the project timeline allows it
The hybrid pattern, which is common in infrastructure teams: write application services and control planes in Go, write hot-path data-plane components in Rust. They interoperate through gRPC, message queues, or FFI. Linkerd is a well-known example: its control plane is largely Go and its sidecar proxy, linkerd2-proxy, is Rust. The same split happens inside other languages too. Python tools like Ruff and uv are Rust underneath, and Django-Bolt puts a Rust HTTP server under a Django API. Each language ends up in the layer where its tradeoffs pay off.
What About Zig?
Zig shows up in every Rust-vs-Go thread, so let me address it briefly. Zig targets the same niche as Rust (systems programming, manual memory management, no garbage collector) but with a simpler syntax and no borrow checker. TigerBeetle is written in Zig. Bun was too, until 2026, when its team ported the runtime to Rust in what its author described as an AI-assisted rewrite, and Bun’s README now describes it as “written in Rust”. The best-known Zig project moving to Rust is, in my reading, a signal about where the libraries and the hiring pool are. Developers who use Zig still like it: Zig was the fourth most admired language in the 2025 Stack Overflow survey at 64%, behind Rust’s 72%.
As of October 2026, Zig is still pre-1.0 (0.17.0 shipped on October 1), has far fewer libraries and tools than either Go or Rust, and the job market is almost non-existent. I’d wait for 1.0. For a backend you need to ship today, the choice is still Go or Rust.
FAQ
Should I learn Go or Rust for backend development?
Learn Go first. You’ll be productive in weeks, more teams already run it, and most backend work is I/O-bound services where Go’s performance is more than sufficient. Add Rust when you have a specific performance or safety problem that Go can’t solve, and don’t put it off for years: in the HN hiring threads sampled above, Rust now shows up in as many startup job posts as Go. If you’re coming from Python or JavaScript, Go’s syntax will feel familiar within days. Rust’s ownership model requires unlearning habits from garbage-collected languages, which is why its ramp-up is measured in months.
Is Rust faster than Go?
Usually, yes, but by how much depends on the workload. The gap is largest for CPU-bound code, tail latency under a large heap (Discord’s Read States case), and memory, where Go’s default GC settings let the heap grow to about twice the live data. For services bottlenecked on database queries and network I/O, the difference is often too small to justify a rewrite. Be skeptical of headline multipliers like “12x” or “5x P99” that don’t come with a published benchmark harness.
Can Rust replace Go?
Rust can do everything Go does, but its longer learning curve, smaller pool of experienced developers and slower builds make it a poor fit for most backend services, where development speed counts for more than runtime performance.
What about Rust vs Go for web development?
Go is the more common choice for server-side web, with frameworks like Gin, Echo and Chi. Rust’s Axum and Actix-web are mature, but the library selection for middleware, ORMs, and template engines is thinner. For a typical web application with user auth, database access, and template rendering, Go will get you to production faster.
Which companies use Rust vs Go in production?
Go: Google, Docker, Uber, Twitch, Dropbox, and most of the Kubernetes toolchain. Rust: Microsoft (reportedly parts of the Windows kernel’s graphics code), Amazon (Firecracker, Bottlerocket), Cloudflare (Pingora), Discord (Read States service), Meta (the Mononoke source control server).
If Go wins your use case, the modern Go guide collects everything we’ve written on the language, and Go CLI frameworks covers the tooling side.
Sources
- Discord: Why Discord is switching from Go to Rust: the Read States case, Go 1.9.2 GC spikes and the Rust results
- A Guide to the Go Garbage Collector: GOGC heap-target formula, GOMEMLIMIT and the GC’s sources of latency
- Go 1.26 release notes: Green Tea garbage collector enabled by default
- Stack Overflow Developer Survey 2025: Technology: language usage and “admired” rankings
- HN Algolia API: data source for the “Who is hiring?” mention counts
- Google Security Blog: Rust in Android: memory-safety vulnerability density for Rust vs C/C++
- Simon Willison: Rewriting Bun in Rust: Bun’s 2026 port from Zig to Rust
- Cloudflare: How we built Pingora: Rust proxy replacing NGINX, with reported CPU and memory savings
- CNCF projects: list of graduated and incubating projects
- RustJobs.dev salary guide: reported Rust compensation data
- JetBrains: Rust vs Go: developer experience comparison
- Bitfield Consulting: Rust vs Go: language design philosophy comparison
Bottom Line
Rust and Go mostly cover different layers. Go holds the application layer (APIs, microservices, DevOps tools, the Kubernetes stack), and Rust is taking the systems layer: kernels, proxies, runtimes, and anything where a GC pause costs money.
If you’re a backend developer choosing your next language, start with Go. More teams run it, the learning curve is flatter, and most backend work fits its sweet spot. When you hit a problem Go can’t solve without burning cloud budget (a hot path eating memory, a P99 blowing its SLA), that’s when Rust earns its complexity. Just know that the job market has moved faster than the folk wisdom: at startups, Rust is no longer the niche pick.
Many backend teams in 2026 already run both, with Go for the services and Rust for the one or two hot paths where the GC math stops working in their favor.