Why Rust?
Rust makes a promise that sounds impossible: memory safety without a garbage collector, and fearless concurrency without data races — all checked at compile time, with no runtime cost. The price is a compiler that argues with you until your program is correct. Understanding that bargain is the key to understanding why Rust exists and why people love it.
Rust is a systems programming language built around a single audacious idea: you can have the safety of a high-level language and the control and performance of a low-level one, at the same time, enforced by the compiler. This series — the Rust companion to this blog’s Go and Python curricula — builds Rust up from the ground. This first post is about why Rust exists: the problem it solves, the bargain it offers, and where it fits. Get the “why” and the rest of the language makes sense as consequences of it.
The problem Rust solves
For decades, systems programmers faced a hard choice between two unhappy options:
- Manual memory management (C, C++) — you control memory directly, giving maximum performance and control, but you’re responsible for freeing it correctly. Get it wrong and you get the notorious bugs: use-after-free, double-free, dangling pointers, buffer overflows, memory leaks, and data races. These aren’t rare — they’re the source of a large fraction of security vulnerabilities and crashes in systems software, and they’re notoriously hard to catch.
- Garbage collection (Go, Java, Python) — a runtime automatically manages memory, eliminating those bugs, but at a cost: the garbage collector uses CPU and memory, introduces pauses (latency you don’t fully control), and adds runtime overhead. For most software this is a fine trade; for the most performance- and latency-sensitive systems, the GC is a real cost.
The choice was: safety or control. You could have a GC’s safety with its overhead, or manual memory’s control with its danger. Rust’s reason for existing is to refuse that choice — to offer memory safety and control at once, with no garbage collector and no runtime overhead, by moving the safety checks to compile time.
The bargain: safety at compile time
Rust’s central idea is that memory safety can be guaranteed by the compiler rather than by a runtime garbage collector or by the programmer’s discipline. The compiler analyzes your code — through the ownership system (the next posts) — and proves it’s memory-safe before it ever runs. If the code could have a use-after-free, a data race, or a dangling pointer, it doesn’t compile.
This is the bargain, and it’s worth stating both sides honestly:
- What you get — memory safety (no use-after-free, no double-free, no dangling pointers, no data races) guaranteed at compile time, with no garbage collector and no runtime overhead. The safety is free at runtime because it’s paid at compile time. You get C-like performance and control with high-level-language safety.
- What you pay — a compiler that is strict, and a learning curve. The compiler enforces rules (ownership, borrowing, lifetimes) that other languages don’t, so it will reject code that would compile elsewhere, until you write it in a way it can prove safe. Early on, this feels like fighting the compiler — the famous Rust learning curve.
The reframe that makes Rust click: the compiler isn’t your adversary, it’s catching real bugs before they ship. The code it rejects would often have been a use-after-free or a data race in C — Rust just catches it at compile time instead of in production at 3 a.m. Once you internalize that “the compiler argues with me until my program is correct,” the strictness becomes a feature: you fight the compiler now so you don’t debug memory corruption later. That mental shift is the single most important thing for learning Rust.
Fearless concurrency
The same ownership system that ensures memory safety also delivers what Rust calls fearless concurrency — a huge deal. Data races (two threads accessing the same data unsafely) are among the hardest bugs in all of software: non-deterministic, hard to reproduce, catastrophic. In most languages, avoiding them is a matter of discipline and hope.
Rust eliminates data races at compile time. The ownership and borrowing rules (which govern who can access data and when) apply to concurrency too, so the compiler proves that your concurrent code has no data races — if it could, it doesn’t compile. This means you can write concurrent code fearlessly: the compiler guarantees the thing that’s normally terrifying. This is a genuine superpower, and it flows from the same ownership system as memory safety — one idea, two profound payoffs. (Later modules cover concurrency in depth; know now that Rust’s safety extends to it.)
Where Rust fits
Rust’s bargain — safety and control without GC overhead — makes it the right tool for a specific and growing set of domains:
- Systems programming — operating systems, embedded systems, device drivers, where you need low-level control and can’t afford a GC.
- Performance-critical software — game engines, databases, browsers, high-performance services, where the GC’s overhead or pauses matter.
- Safety-critical software — where memory-safety bugs are unacceptable (security-sensitive systems, infrastructure), Rust’s guarantees are invaluable.
- WebAssembly, CLI tools, and increasingly backend services — Rust has spread well beyond its systems roots into anywhere performance and reliability matter.
And where Rust isn’t the obvious choice: for many applications where a GC’s overhead is irrelevant and development speed matters more, a garbage-collected language (Go, Python) is simpler and faster to write — you pay for Rust’s guarantees with the learning curve and the compiler’s strictness, and if you don’t need those guarantees, that price may not be worth it. Rust shines when its specific bargain — maximum safety and performance and control — is what the problem demands. (This is the same match-the-tool-to-the-problem reasoning as choosing any language.)
Where the series goes
This first module builds Rust’s foundations, all of which are consequences of the safety-without-GC bargain: the toolchain (Cargo), variables and types (immutability by default), and then the trio that is Rust’s soul — ownership, borrowing, and lifetimes — followed by structs, enums, pattern matching, and Rust’s exception-free error handling (Result and Option). Ownership is the hardest and most important idea, and everything distinctive about Rust flows from it, so we build carefully toward it. By the end you’ll understand not just Rust’s syntax but why it’s shaped the way it is — as the language that keeps its impossible-sounding promise by moving safety to compile time.
Key takeaways
- Rust exists to refuse the old systems-programming choice between safety and control: it offers memory safety and low-level control/performance at once, with no garbage collector, by moving safety checks to compile time.
- The bargain: you get compile-time-guaranteed memory safety (no use-after-free, double-free, dangling pointers, or data races) with no runtime GC overhead — paid for with a strict compiler and a learning curve that rejects code it can’t prove safe.
- The key mental shift is that the compiler isn’t your adversary but a bug-catcher: the code it rejects would often be a use-after-free or data race in C, so you fight the compiler now instead of debugging memory corruption in production.
- The same ownership system delivers fearless concurrency — data races (among the hardest bugs anywhere) are eliminated at compile time, so you can write concurrent code the compiler proves race-free — one idea (ownership) with two profound payoffs.
- Rust fits systems, performance-critical, and safety-critical software (and increasingly WASM, CLIs, and backends) where its safety-and-performance bargain is needed; a GC language may be simpler where that bargain isn’t required.
Further reading
- The Rust Programming Language (the official book)
- Road Go Ever On — the Go curriculum
- Python Programming — the Python curriculum