The popular line is that Rust beat C++ on safety alone. That’s only half the story, and the smaller half. Here’s how a one-person side project ended up in the Linux kernel.
There’s a claim you hear constantly, that developers are switching to Rust because of its borrow checker and memory safety, full stop. I’d push back on that. Safety is the headline, sure, but it’s not why most teams I’ve watched actually made the jump. They jumped because the whole package around the language turned out to be better, and the safety guarantees were the part that let them justify the move to a skeptical manager. Plenty of languages promise safety. Very few of them ship with a build system you don’t end up hating, a package registry that works the same on every operating system, and a compiler that explains your mistakes instead of just listing them. Strip out the borrow checker entirely and Rust would still have pulled people away from C++. Slower, maybe. Less of a security story, certainly. But it would’ve happened.
What’s more interesting than the safety pitch is the path the language took to get taken seriously. One Mozilla engineer’s frustration in 2006 turned into something that Amazon and Microsoft and Google and Discord all decided to put real money behind, and eventually the Linux kernel maintainers too. That arc runs about twenty years. Walking through it explains the adoption better than any feature list does, so I’d rather organize this around the ideas that moved the needle than march through it year by year.
One person, one annoyance
Graydon Hoare started Rust as a personal project in 2006. He’d gotten tired of the same category of bug that haunts systems code: dangling pointers, data races, use-after-free errors. Mozilla took notice around 2009 and started funding the work, and the reason wasn’t charity. Firefox’s C++ codebase was a steady producer of exactly those bugs, and memory corruption inside a web browser isn’t a theoretical worry. It’s a security hole that millions of people walk around with installed.
At that stage Rust didn’t look like a contender. Experimental syntax, a community you could fit in a small room, no ecosystem worth the name. Most working programmers had never heard of it, and the ones who had were skeptical, which was reasonable. New languages appear constantly and almost all of them quietly disappear. From the outside there wasn’t an obvious tell that this one would survive, let alone end up where it did.
Servo as the proving ground
Mozilla did something other language sponsors mostly don’t. Rather than fund a language and wait around for developers to materialize, they committed to building a serious piece of software in it. Servo was a web rendering engine written from scratch, and it doubled as a stress test and a demo. Could Rust handle parsing HTML, laying out CSS, compositing layers, and running all of that across multiple threads without the data races that every other browser engine had bled over for years?
Turned out it could. Servo showed that the ownership model, where every value has exactly one owner and the compiler tracks borrowing, wasn’t just an academic nicety somebody had dreamed up. Real concurrency bugs got caught at compile time, the kind that would’ve meant days of misery to track down in C++. And the performance held up. Not “respectable for a safe language” performance. Genuinely competitive with C++ engines carrying years of hand-tuning. Through this stretch the language churned hard. Features got added, ripped out, redesigned. Lifetimes, traits, pattern matching, the borrow checker, all of it got hammered into shape by feedback from Servo and the early adopters willing to live with a target that wouldn’t hold still.
The promise that mattered more than any feature
Rust 1.0 shipped on May 15, 2015. The language wasn’t finished, languages never are, but that release carried a stability guarantee, and that’s what made it a real event. Code written against 1.0 would keep compiling on every version that came after. For anybody weighing whether to put production systems on a young language, that promise outweighs any single feature you could name. Nobody sane rewrites critical infrastructure in a thing that might break their build on the next point release.
Reception ran cautious. Some C++ veterans waved it off. Others got curious. Stack Overflow’s developer survey that year tagged Rust as the most loved language, a spot it would keep holding for years afterward. “Most loved” and “most used” aren’t the same thing though, and adoption stayed tiny next to C++, Java, or Python. What stood out was the retention. People who tried it kept coming back, and they wouldn’t shut up about why.
Cargo, and why tooling did half the selling
Here’s where I’d locate a chunk of the real explanation, and it has nothing to do with memory. Cargo is probably Rust’s biggest practical edge over C++, and it gets undersold every time the conversation drifts back to safety. One build system. A single package manager that behaves identically on Linux and macOS and Windows. Pulling in a dependency means adding one line to a TOML file. Set that next to the C++ situation, where on any given day you might be wrestling CMake or Conan or vcpkg or Bazel or some hand-rolled Makefile horror somebody left behind, and the gap in daily experience is hard to oversell. From what I’ve seen, that gap alone talked a lot of people into giving Rust a serious afternoon.
The registry behind it grew the same way. Crates.io went from a few thousand packages to tens of thousands as smaller shops and open-source projects started reaching for Rust on new work, networking tools, command-line utilities, embedded experiments. None of it individually earth-shaking. Collectively it filled the gaps, async I/O, serialization, HTTP, cryptography, the libraries you need before a language is usable for anything real.
When the case stopped being a vibe
Dropbox made one of the early visible bets, somewhere in the 2016 to 2018 window. They rewrote parts of their file synchronization engine in Rust, retiring Python code that couldn’t keep pace with syncing billions of files across hundreds of millions of accounts. Their engineers wrote about it publicly: Rust’s type system caught bugs during development that would otherwise have surfaced as production incidents. Not cosmetic bugs either. The data-corrupting, silent-failure variety.
Discord’s post in early 2020 might’ve done more for Rust’s industry credibility than anything else, and I’ll explain why I think that. They’d rewritten a service from Go to Rust, and the problem was specific and legible. Go’s garbage collector threw latency spikes during collection pauses, and for a real-time chat platform carrying millions of concurrent users, those spikes were a dealbreaker. Rust carries no garbage collector. Freed deterministically when an owner falls out of scope, memory just goes away. No pauses, no surprises. Their rewritten service ran faster and more predictably, and the type system swept up concurrency bugs that would’ve been brutal to reproduce in production. Discord kept going from there, putting Rust into their read states service, message indexing, other latency-sensitive pieces. Why that post landed harder than the Dropbox one comes down to numbers. Before-and-after latency graphs. Throughput figures. Memory usage, charted. An engineer at some other company could open that post and build a business case out of it, which is a very different thing from “a language some people on the internet like.”
The names that ended the “too immature” argument
Amazon Web Services built Firecracker in Rust, the lightweight microVM that sits under Lambda and Fargate. When AWS writes core infrastructure in your language, the room goes quiet. Microsoft started poking at Rust for Windows components after admitting that roughly 70% of its security vulnerabilities traced back to memory safety issues. Seven in ten. That’s not an edge case you can shrug off. Of every ten security bugs in one of the most widely deployed software products on earth, seven sat in the precise category Rust’s compile-time checks rule out.
Google pulled Rust into parts of Android and Chrome OS. Cloudflare built large pieces of its edge platform on it. February 2021 brought the Rust Foundation, backed by AWS and Google and Huawei alongside Microsoft and Mozilla. A foundation with corporate money behind it doesn’t make a language good. What it signals is that the thing won’t evaporate because one sponsor reshuffles its priorities, and for risk-averse buyers that signal carries weight. By then crates.io was hosting over 70,000 packages. Tokio, the async runtime, had been beaten on across heavy production deployments. Serde had quietly become a library everyone just assumed would be there. Actix and later Axum gave you web frameworks that could trade throughput punches with Go and Java. Arguing Rust was unproven had gotten difficult to do with a straight face.
Into the kernel
Late in 2022, Linux 6.1 merged initial Rust support, and it’s genuinely hard to overstate the size of that. Linux runs the world’s phones, servers, embedded gear, supercomputers, cars, even refrigerators, and Linus Torvalds has never been the type to adopt a thing because it’s fashionable. The kernel community argued for years over whether a second language belonged alongside C at all, and they landed on yes. Kernel developers can write modules in Rust now, and the safety guarantees don’t politely vanish at that level. If anything they count for more down there, where one memory bug can take down an entire machine or hand someone a privilege escalation. Early kernel Rust leaned toward driver work, where bugs run common and the blast radius is severe, and that’s probably where the language lands its first real impact inside the kernel.
What the language actually does
Ownership sits at the center. Every value in Rust has one owner, and when that owner leaves scope, the value gets dropped. No garbage collector. There’s no reference counting either, unless you deliberately ask for it. Because the compiler enforces all of this before the program ever runs, the safety checks cost nothing at runtime. Your binary moves as fast as the equivalent C++ binary, occasionally faster, since the compiler can apply optimizations that wouldn’t be sound without the ownership guarantees underneath them.
Borrowing builds on that. You can lend out a reference, with one catch the compiler enforces absolutely: either a single mutable reference, or any number of immutable ones, never the two together. It sounds restrictive because it is. Those exact restrictions are also why data races can’t occur. Not “probably won’t,” not “our static analyzer came up empty.” Can’t. Code with the possibility of a data race in it simply won’t compile, full stop.
Error handling runs through the Result and Option types instead of exceptions. A function that might fail hands back a Result. Anything that might be missing becomes an Option. Both cases have to be handled because the compiler refuses to let you skip them. C++ exceptions drag along their familiar baggage: control flow you can’t trace by reading, performance overhead in some implementations, and the perpetual guessing game of which functions throw and which don’t. Rust steps around the whole mess. Pattern matching, algebraic data types, traits in place of inheritance, zero-cost abstractions, there’s a lot more under the hood. Ownership and the borrow checker are still what set it apart from the field. Other languages have sharp type systems. Plenty of them match patterns just as well. Rust’s the one that blocks memory bugs and data races at compile time without leaning on a garbage collector to do it.
Where C++ keeps the high ground
Ecosystem depth, first. Go looking for a library covering some obscure signal-processing routine or one specific piece of hardware, and odds are a C++ implementation already exists while the Rust one doesn’t. Interop with C stays trivial in C++ and asks for more ceremony in Rust, though cxx and bindgen take the edge off. And if you’re sitting on ten million lines of working C++, nobody credible is telling you to rewrite it. That’s years of effort and a fortune in payroll for a result you already have.
Compile times are a fair complaint, and I won’t pretend otherwise. Rust builds slower than comparable C++ projects. Borrow checking, monomorphization of generics, and LLVM-based code generation each add their own tax. Incremental compilation eases the day-to-day grind, but a clean build of a large project can still test your patience badly. Release by release the compiler team chips away at it, and each one tends to land a little quicker, though the problem’s far from closed out.
Embedded and real-time work still tilts hard toward C and C++. Rust’s embedded story has come along, Embassy is a genuinely impressive async embedded framework, but the tooling, the hardware support libraries, and the decades of institutional knowledge around embedded C run deeper. Could be wrong, but my guess is it takes another three to five years before Rust becomes a default pick for most embedded jobs.
The learning curve, which is real
No point pretending the curve is gentle. That borrow checker will reject code that looks completely fine to a C++ programmer, and while the error messages are genuinely good and often hand you the exact fix, parsing them still demands understanding ideas that don’t exist in most other languages. Lifetimes trip people up worst. Trait bounds get hairy. Generic code occasionally throws an error message you have to sit with for a minute before it clicks. From what I’ve gathered talking to people who made the switch, the frustration tends to peak around the second or third week and then falls off a cliff. Something settles into place. You start reasoning about who owns what before you write the code rather than after the compiler yells, and your designs come out cleaner for being forced to say so out loud. A month or two in, productivity reads about even with C++, and probably ahead of it, since you’ve stopped losing afternoons to memory corruption.
“The Rust Programming Language,” the one everybody calls “the book,” sits online for free and runs from basics through the advanced material. Rustlings hands you interactive exercises. By most accounts the community treats newcomers well, even if it can get a touch evangelical about how great Rust is. They’re not wrong about that, to be fair. Just a lot, sometimes.
Hiring and the premium that won’t last forever
Rust roles pay well right now, and the supply of seasoned Rust developers still trails demand. Companies posting Rust jobs report fielding stronger applicants on average, which might be plain selection bias, since the kind of person who goes and learns Rust tends to already care about correctness and tolerate complexity. If you’re a C++ developer eyeing your next move, Rust on the resume opens doors that flatly didn’t exist five years back. I doubt the premium holds indefinitely. As the pool of Rust developers fills out, the supply gap narrows and the bonus erodes with it. For the next few years, though, the skill carries a markup.
If you’re weighing the switch
Start small. A command-line tool, a data-munging script, something self-contained where you can wrestle that checker with no production deadline breathing on you. Don’t try to write C++ in Rust. The idioms differ, the patterns differ, and forcing C++ habits through the ownership model produces ugly, miserable code that fights you the whole way.
Read the compiler errors, all of them. They’re written to teach rather than just to reject. When it complains about a borrow, resist the urge to clone everything in sight until things compile. Sit with what it’s telling you instead, because nine times in ten there’s a cleaner design hiding right behind the error. And you don’t have to walk away from C++ to do any of this. Plenty of teams run both. Write the new performance-sensitive components in Rust, keep maintaining the existing C++, bridge the two with FFI where it’s needed. Gradual adoption works fine, and for any shop sitting on a large C++ codebase it’s probably the only realistic route anyway.
The state of play
By the 2023 to 2025 stretch, something shifted that had nothing to do with engineers. The White House Office of the National Cyber Director put out a report pressing developers toward memory-safe languages, and CISA followed with similar guidance. These reports named C and C++ by name as sources of preventable vulnerabilities and pointed at Rust as one answer. Government reports don’t compel anybody to do anything directly. What they do is reshape procurement rules, compliance checklists, and corporate risk math, and that’s where the pressure actually bites. Conversation moved from “Rust is neat” to “memory safety is a national-security problem and here’s a language that addresses it.” Defense contractors, banks, healthcare outfits, regulated industries generally, started watching. Not all of them are writing Rust yet. More of them are running pilots than were a couple of years ago.
The tooling kept maturing alongside the policy noise. Crates.io passed 130,000 packages. Async Rust got smoother with each release. IDE support through rust-analyzer climbed to a level that holds up next to what Java and TypeScript people take for granted. Clippy, the linter, flags hundreds of common mistakes and nudges you toward more idiomatic code, and Rustfmt enforces one formatting style across the whole ecosystem, so the brace-placement arguments just don’t happen.
So where does that leave things. Rust’s registry holds over 130,000 crates. The kernel takes Rust code. AWS and Microsoft and Google run it in production, as do Cloudflare and Discord and Dropbox. Government agencies recommend memory-safe languages out loud. Async is mature, tooling is strong, the community’s large and busy. Compile times are still slow, the embedded ecosystem still has holes in it, and the learning curve still humbles experienced programmers for a few weeks. None of that reads as hype to me. It reads as a language that solved one specific and genuinely important problem, memory safety without a garbage collector, then spent fifteen years proving the solution holds up in practice. C++ isn’t going anywhere. Too much code, too much accumulated knowledge, too many domains where it’s dug in to the foundations. For brand-new systems projects where safety and correctness are the whole point, though, Rust is the default for a growing share of teams, and that share climbs every quarter.



(0) Comments