You shouldn’t use Rust (probably)
"We're going to build everything in Rust for performance," the engineering lead announced confidently. Six months later, they were still debugging borrow checker errors while their competitors had shipped three major features using boring old Java.
I've been thinking a lot lately about technology choices and their unintended consequences. Specifically, how the allure of a "better" programming language can lead teams down rabbit holes that have nothing to do with the problems they're actually trying to solve.
The Rust Trap
Don't get me wrong - Rust is an incredible language. Memory safety without garbage collection, fearless concurrency, blazing fast performance. It's genuinely revolutionary for systems programming, operating systems, embedded devices, and performance-critical applications.
But here's the thing: most of us aren't building operating systems.
I recently worked with a company that had decided to use Rust for everything. Every microservice, every API, every background worker - all Rust, all the time. The reasoning was simple: "We want the best performance possible."
The reality was more complex. This wasn't a high-frequency trading platform or a real-time graphics engine. It was a fairly standard SaaS application - user management, billing, some data processing, the usual suspects. The kind of system that thousands of companies have built successfully with Java, C#, Python, or Node.js.
When Performance Isn't the Problem
Here's what I've learned from working on distributed systems: performance bottlenecks are rarely where you think they are, and they're almost never solved by switching programming languages.
In a typical SaaS architecture, you're usually bottlenecked by:
- Database queries that could use better indexing
- Network latency between services
- Third-party API calls
- I/O operations waiting for file systems or external services
- Poorly designed algorithms that make unnecessary work
CPU-bound performance - the kind where Rust's zero-cost abstractions actually matter - is surprisingly rare in business applications. Most microservices spend their time waiting: waiting for databases, waiting for HTTP responses, waiting for file uploads to complete.
In these scenarios, the difference between Rust's blazing speed and Python's "sluggish" performance is completely invisible. Whether your authentication service responds in 2ms or 5ms doesn't matter when the database query takes 50ms.
The Hidden Costs of Complexity
But the performance story is just the beginning. The real issue with choosing Rust for typical business applications is the complexity tax you pay every single day.
Rust has a notoriously steep learning curve. The borrow checker, while brilliant for memory safety, requires a fundamentally different way of thinking about data ownership. Experienced developers can spend weeks just learning how to make the compiler happy, let alone writing idiomatic, maintainable code.
This means:
- Slower onboarding for new team members
- More time spent fighting the language instead of solving business problems
- Fewer available developers in the hiring pool
- Increased debugging complexity when things go wrong
For a typical SaaS company, these costs far outweigh the theoretical performance benefits you'll never actually need.
The Reinvention Problem
Here's where things get really interesting, and where I think Rust's appeal can become actively harmful to productivity.
The team I mentioned earlier didn't just choose Rust - they ended up building their own worker queue library. From scratch. Complete with retry logic, dead letter queues, the works.
In the Python world, this would have been unthinkable. You'd install Celery, write a few configuration lines, and move on with your life. The ecosystem provides battle-tested solutions for common problems.
But something about Rust seems to attract engineers who enjoy building foundational infrastructure. Maybe it's the systems programming heritage, maybe it's the type of developer who's drawn to Rust in the first place. Whatever the reason, I've noticed a pattern: Rust teams tend to reinvent wheels that already exist in more mature ecosystems.
This isn't necessarily malicious or even conscious. Building a worker library is an interesting technical challenge. It involves concurrency, error handling, persistence - all the kinds of problems that Rust handles elegantly. It's easy to convince yourself that your custom solution will be "better" than the existing alternatives.
But here's the thing: you're not in the worker library business. You're in the business of building whatever SaaS product your company actually sells. Every hour spent reinventing infrastructure is an hour not spent shipping features that customers will pay for.
The Ecosystem Maturity Gap
This brings up another crucial point: ecosystem maturity matters enormously for developer productivity.
Java has decades of libraries, frameworks, and tooling. Need to integrate with Stripe? There's a well-maintained SDK. Want to process CSV files? Pick from dozens of battle-tested libraries. Need to implement OAuth? Spring Security has you covered.
C# has similarly rich ecosystem support, with NuGet packages for virtually every common use case and excellent tooling throughout.
Python might be "slow," but Django will have you building complete web applications in hours, not weeks. The standard library is comprehensive, and PyPI has packages for everything under the sun.
Rust's ecosystem, while growing rapidly, simply isn't there yet for typical business application development. You'll spend time finding, evaluating, or building basic functionality that would be trivial in more established languages.
When Rust Makes Sense
I don't want this to sound like a complete condemnation of Rust. There are absolutely scenarios where it's the right choice:
- Performance-critical systems where every millisecond matters
- Systems programming where memory safety is crucial
- Embedded systems with resource constraints
- High-throughput, CPU-intensive workloads
- Infrastructure that needs to handle massive scale efficiently
But here's the key: these are specific use cases with specific requirements. If you can't articulate exactly why you need Rust's particular advantages, you probably don't.
The Architecture Principle
The fundamental insight here is that architecture matters far more than language choice for most applications.
A well-designed system with proper caching, efficient database queries, and smart service boundaries will outperform a poorly designed system every time, regardless of whether it's written in Rust or Ruby.
Focus on:
- Choosing the right database for your use case
- Implementing effective caching strategies
- Designing services with clear responsibilities
- Optimizing the queries that actually matter
- Using CDNs and geographic distribution appropriately
These architectural decisions will have 100x more impact on your system's performance than switching from Java to Rust.
The Boring Technology Principle
There's wisdom in Dan McKinley's "Choose Boring Technology" principle. Your business probably has a limited budget for innovation and complexity. Spend it on the parts that actually differentiate your product, not on the programming language choice.
If your team already knows Java well, building your SaaS in Java lets you focus on solving customer problems instead of learning new syntax. If your company has Python expertise, Django will get you to market faster than any amount of Rust optimization.
Boring choices free up mental bandwidth for the interesting challenges that actually matter to your business.
The Real Performance Questions
Instead of asking "Should we use Rust for performance?", ask:
- What are our actual performance requirements?
- Where are our current bottlenecks?
- What would happen if our API took 100ms instead of 10ms?
- Are we CPU-bound or I/O-bound?
- How much complexity are we willing to trade for theoretical performance gains?
Most of the time, the honest answers to these questions point away from Rust and toward simpler, more established solutions.
Final Thoughts
I'm not anti-Rust. It's a remarkable achievement in language design, and I genuinely admire what the community has built. But like any powerful tool, it's frequently misapplied.
The next time someone suggests using Rust for your team's next project, push back gently. Ask what specific problem it's solving that can't be solved more simply with existing tools. Ask whether the team has actually profiled the current system to identify performance bottlenecks. Ask whether the added complexity is worth the theoretical benefits.
Most importantly, remember that the goal isn't to use the coolest technology - it's to build software that solves real problems for real people. Sometimes that means choosing the boring, battle-tested option over the shiny new thing.
Your customers don't care what programming language you used. They care whether your software works, whether it's reliable, and whether you can ship new features quickly when they need them.
Choose accordingly.
Have you seen teams get distracted by technology choices that didn't match their actual needs? How do you balance innovation with pragmatism in your technical decisions?