Why Rust Won't Replace C

Rust is excellent technology. C has economics, ecosystems, and human factors on its side.

Illustration for Why Rust Won't Replace C
rust-wont-replace-c Rust is safer than C. That's not enough. Trillions of lines of C are in production. The learning curve is brutal. Safety-critical domains require certified toolchains. Technology quality doesn't drive technology adoption—economics does. Rust, C programming, systems programming, memory safety, Linux kernel, programming languages, embedded systems, language adoption, Rust vs C

According to GitHub's 2024 Octoverse report, Rust adoption grew 40% year-over-year. C's market share fell to around 10% in the TIOBE Index. The "rewrite it in Rust" movement is louder than ever. And yet C will still be here in 50 years when most of today's Rust codebases are legacy systems nobody wants to maintain.

TL;DR

Don't rewrite C systems in Rust for safety alone—economics trumps elegance. Learn C to understand how systems actually work. Rust is for new projects, not rewrites.

I understand why teams adopt this approach—it solves real problems.

The Rust community loves to point at C's memory safety problems. They're right that C lets you shoot yourself in the foot. But I've worked with both languages in production for over 30 years, and they're wrong that Rust is the answer for most systems that currently use C. The economics, ecosystem, and human factors all work against replacement.

This isn't about Rust being bad. Rust is impressive technology. This is about understanding why technology replacement is harder than technology invention.

Updated January 2026: Added ABI stability analysis, economic cost modeling, and Monday Morning Checklist.

The Trillion-Line Problem

Here's the number that matters: trillions of lines of C are in production today. The Linux kernel alone is over 27 million lines. Every embedded system in your car, your pacemaker, your thermostat. Every database kernel, every operating system, every network stack.

Meanwhile, as DevClass reported, Rust represents 0.1% of the Linux kernel codebase. After years of effort and intense advocacy, Rust is now officially supported in the kernel with 143 separate files. That's progress, but it's not replacement. It's coexistence.

The math is brutal. If every Rust developer on Earth worked full-time rewriting C code, it would take decades just to address the most critical systems. That assumes they match original productivity and make no mistakes requiring rework. Nobody is working full-time on this. It's a side project for most organizations.

The Economic Suicide Pact

The "rewrite it in Rust" crowd treats this as a technical problem. It's not. It's an economic suicide pact.

Let's quantify. The Linux kernel has ~27 million lines of C. At an optimistic 50 lines per developer-day (accounting for testing, review, and bug fixing), that's 540,000 developer-days. At $500/day fully-loaded cost, you're looking at $270 million just for the kernel. And that's assuming perfect productivity—no bugs, no rework, no domain learning curve.

Now multiply across every C codebase in production: PostgreSQL (1.5M lines), SQLite (150K lines), nginx (200K lines), every embedded system, every network stack. The global "rewrite bill" is in the hundreds of billions of dollars. For what? To eliminate bugs that mature codebases have already fixed?

This is The Rewrite Trap at civilizational scale. The economics don't work. They never will.

The ABI Problem Nobody Mentions

Here's the technical reason Rust cannot replace C as the systems programming lingua franca: Rust refuses to stabilize its ABI.

C's Application Binary Interface has been stable for decades. A shared library compiled with one C compiler works with code compiled by another. This is why every language on Earth can call C code. Python, Ruby, Java, Go—they all use C as their foreign function interface. C is the universal adapter.

Rust has no stable ABI. The Rust team has explicitly said they have no plans to stabilize it. Every Rust library must be compiled with the exact same compiler version as the code calling it. Want to ship a Rust shared library? You're either shipping source code or locking everyone to your exact toolchain version.

This isn't a bug—it's a design choice that enables compiler optimizations. But it means Rust cannot be the foundation layer that C is. You cannot build a stable operating system API in Rust. You cannot ship Rust shared libraries to arbitrary consumers. Rust is a walled garden. C is the public square.

The Learning Curve Nobody Wants to Pay For

Rust's borrow checker is genuinely innovative. It catches memory safety bugs at compile time that would be runtime disasters in C. It's also, by many accounts, brutal to learn.

According to Bits&Chips' analysis of Rust adoption, around 30% of Rust newcomers quit early due to the learning curve. The ownership model that makes Rust safe also makes it unlike any mainstream language. You're not just learning syntax. You're learning a new way of thinking about memory.

Industry surveys show developers describing the curve as "not just steep, but vertical." Async programming in Rust is particularly challenging. By the time developers are comfortable with basics, async adds another conceptual layer. Many find it overwhelming.

C has problems, but inaccessibility isn't one of them. A competent programmer can be productive in C within weeks. The same programmer might spend months fighting the borrow checker before achieving similar productivity in Rust. For organizations maintaining legacy C systems, that's a hard sell.

Consider returning the longer of two strings. In C, it's straightforward:

// C: Simple and direct. Caller manages memory.
char* longest(char* a, char* b) {
    return strlen(a) > strlen(b) ? a : b;
}

char* result = longest(str1, str2);  // Just works

The same function in Rust requires lifetime annotations:

// Rust: Must specify lifetime relationships
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.len() > b.len() { a } else { b }
}

// Compiler enforces: result can't outlive either input
let result = longest(str1, str2);

The Rust version is safer—it prevents dangling references at compile time. But it's also more complex. That 'a lifetime parameter isn't just syntax; it's a concept that takes weeks to internalize. According to the Rust Book, "Lifetime annotations don't change how long any of the references live. Rather, they describe the relationships of the lifetimes of multiple references to each other." Understanding that sentence takes longer than writing the C version.

Where the Rust Hype Meets Reality

The success stories are real. Discord rewrote their voice system from Go to Rust and cut CPU usage from 20% to under 5%. Dropbox replaced their Python storage backend with Rust and slashed memory usage by 75%. These are genuine wins.

But notice what they replaced: Go and Python. High-level garbage-collected languages where Rust's performance advantages are obvious. Replacing C is a different proposition entirely.

Rust achieves near-C performance while adding compile-time safety. That's impressive, but it's not "faster than C." It's "as fast as C, with a harder learning curve, for more safety." For systems already written in C by experts, the value proposition is less clear.

AWS Engineer Russell Cohen made this point at the 2025 Rust Conference: "To migrate to Rust, you should have a genuine reason or an actual problem to solve." Not "C is old" or "Rust is cool." An actual problem.

The Domains C Won't Soon Leave

Some domains have constraints that make Rust adoption impractical:

Safety-critical embedded systems. Automotive, aerospace, and medical devices require certified toolchains with decades of validation. C compilers for these domains have been tested against formal specifications for years. Rust toolchain maturity simply isn't there for certifications like DO-178C or ISO 26262.

Extreme resource constraints. When you have 2KB of RAM and 16KB of flash, every byte matters. C's minimal runtime and predictable output size make it the only practical choice. Rust's runtime still adds overhead that matters at these scales.

Legacy integration. Systems that need to interface with 30-year-old hardware or custom silicon often have C as their only documented interface. The FFI overhead and complexity of wrapping these in Rust often exceeds the safety benefits.

I've written about why C represents a philosophy that modern languages have abandoned. That philosophy of programmer control and machine transparency matters in these domains.

The Maintenance Nightmare Nobody Discusses

The "rewrite it in Rust" advocates focus on the rewrite. In my experience leading engineering teams, they don't talk about what happens after. Here's what actually happens:

That C codebase you're replacing? It has 20 years of bug fixes and hard-won knowledge encoded in it. I've seen this pattern destroy rewrites repeatedly. The original developers understood the problem domain deeply. Their code handles corner cases you don't even know exist.

When you rewrite, you don't port that knowledge. You recreate it through painful experience. The bugs fixed in 2008 will come back. The performance optimizations a now-retired engineer spent months on will be lost. You'll ship something that works on the happy path and fails in production.

This pattern shows up everywhere. Comprehension debt isn't just about AI-generated code. Any code you didn't write yourself and don't fully understand creates maintenance burden. Rewrites create comprehension debt at scale.

The Hiring Reality

The 2025 Stack Overflow survey shows Rust as the most admired language for the ninth consecutive year. 72% of developers want to continue using it. But admiration doesn't equal adoption.

Try hiring a Rust team in 2026. Supply is limited and salaries are 15-20% higher than equivalent C/C++ roles. You can hire experienced C developers at market rates. Or pay a premium for Rust developers who'll spend their first year learning your codebase while fighting the borrow checker.

The Rust developer pool is growing, but it's still a fraction of the C/C++ talent available. The best Rust developers want greenfield projects, not maintenance rewrites of legacy systems.

What's Actually Happening

The realistic pattern isn't replacement. It's hybrid adoption:

  • New components in Rust. When Linux's DRM maintainer says new drivers should be in Rust, that's new code, not rewrites.
  • Security-critical paths in Rust. Android's ashmem memory allocator shipped in Rust because that specific component handles untrusted input.
  • C staying where it works. The 98% of the Linux kernel that's still C isn't going anywhere.

Microsoft's goal to "eliminate every line of C and C++ by 2030" is aspirational, not operational. They're talking about new development guidelines, not mass rewrites of Windows internals. Marketing writes checks engineering can't cash.

This is similar to what happened with open source maintainer burnout. The community has ambitions that exceed its resources. The work is harder than the advocates acknowledge.

The Real Competition

Rust's actual competition isn't C in its strongholds. It's C++ in its weak spots, Go in systems programming, and C in greenfield projects.

For new infrastructure where performance and safety both matter, Rust is often the right choice. For web services that don't need C-level performance, Go is simpler. For embedded systems with mature toolchains, C remains dominant.

The "rewrite everything in Rust" movement misunderstands this. Technology transitions happen at the margins first. C won't be replaced. It will be gradually surrounded by Rust in contexts where Rust's trade-offs make sense.

Language Choice Decision Matrix

Match your constraints to the right language. Ideology doesn't ship products.

Your Constraint Best Choice Why
Safety certification (DO-178C, ISO 26262) C Decades of certified toolchains
Extreme resource limits (<16KB flash) C Minimal runtime, predictable size
Existing C codebase maintenance C Rewrite cost exceeds benefits
Stable ABI for shared libraries C Rust ABI intentionally unstable
New security-sensitive code Rust Memory safety at compile time
New performance-critical infrastructure Rust C-level speed with modern tooling
Web services, network code Go or Rust Safety + simpler concurrency
Team has C expertise, no Rust C Learning curve costs real money

The Rule: Use Rust for new code where memory safety is critical and you can afford the learning curve. Keep C where it works, where certification matters, or where the rewrite cost exceeds the safety benefit.

Rewrite Cost Calculator

See what the "rewrite it in Rust" ideology actually costs.

Linux kernel: 27M, SQLite: 150K, nginx: 200K
$10/line is optimistic for mature code

The Bottom Line

Rust is excellent technology that solves real problems. It achieves safety without sacrificing performance.

But technology quality doesn't drive technology adoption. Economics does. Hiring does. Existing codebases do. Toolchain maturity does. On all these dimensions, C's advantages will persist for decades.

The future isn't C or Rust. It's both, used where each makes sense. C for the foundations, the resource-constrained, the safety-certified. Rust for the new, the security-sensitive, the greenfield. Anyone telling you Rust will replace C is selling a vision, not describing reality.

"But technology quality doesn't drive technology adoption. Economics does. Hiring does. Existing codebases do."

Sources

Technology Strategy

Choosing languages for critical systems requires understanding adoption dynamics beyond technical merit. Get perspective.

Contact Us

Found a Better Way?

If you've solved these problems differently—especially if your solution is simpler—share it.

Send a Reply →