Should I Rust or should I go?

"Is Rust a great fit for this project?"

I get this question quite frequently so I think it's time to write down my thoughts if it can avoid you some painful and costly mistakes.

Short answer: no.

Coming from someone who wrote a successful book about Rust (Black Hat Rust) it may be surprising. So, if like me, you are never satisfied with a short answer without an explanation, keep reading.

First, why the title? Rust and Go are absolutely not the only available languages, but, in my experience, when people are hesitating if they should chose Rust for their new project, the second choice is almost always Go. And most of the time, Go is the right choice, being almost as easy to use as Python, and being faster and more reliable than Java.

Rust is (over)hyped

Rust was Stack Overflow's most loved language for 7 years in a row (they replaced loved/dreaded by admired/desired in 2023), and yet, was ranked as the 14th most used in 2022.

There is a clear mismatch between what people desire and what they do in the real world. Sometimes, I feel that Rust is like the metaverse: a lot of people are talking about it, but not many spend their days in it.

Rust projects decay

Between January 2020 and September 2023 Rust has seen 31 releases, which amounts to 4500 lines of changelog. And this is before talking about Rust "editions" which bring even more confusion for newcomers.

So, if you think that you didn't have enough work solving the problems of your users, you now also need to update your toolchains, Dockerfiles, dependencies and more, every 6 weeks. Programming languages are platforms, not products. They should be stable and move slowly so that most of the time of your develoeprs is not spent fighting with their tools.

Also, features compound over time and lead to unmanageable complexity.

Features compound over time

A language that moves too fast brings a lot of churn to the ecosystem as some developers are eager to include the new feature of the month in their libraries which leads to a lot of busywork without bringing any value to anybody.

It's not uncommon in the professional world™ to have a project that is left untouched for 3 years and then suddenly needs an update. Now imagine being the one tasked with updating the dependencies of a service that is 31 versions behind...

During the same period, there was 8 Go releases, 7 Node.js releases (but only 2 LTS) and 3 Python releases.

Rust is still beta (despite the 1.0)

Related to the point above, Rust is actually still in the beta phase, with some important features such as async Traits still missing, which brings more churn to the ecosystem.

The standard library is anemic

Today, the prevailing opinion seems to be that Rust's standard library must be thin and most of the features left to 3rd party packages to avoid stagnation.

I'm not a fan of this approach due to the big attack surface that it opens to supply chain attacks and backdoors, but also because you then have many implementations and ecosystems competing for basic features such as cryptographic primitives, async runtimes or HTTP servers, leading to incompatibilities, bugs, busywork and lost time.

I think that a modular and rich standard library such as Go's or Node.js's offers way higher productivity to developers, consistency to the ecosystem and reduced costs for organizations.

async is hard

The absolute first thing I do when I audit Rust code is to look for sync functions blocking the event loop which often leads to hard-to-debug performance inconsistencies or even potential Denial of Service (DoS). I don't remember any project with more than a few thousands lines of code that DIDN'T had at least one occurence of blocking the event loop. Put another way, async is more often just another way to shoot yourself in the foot than a real advantage.

Also, async makes understanding and designing ownership, Rust's most (in)famous feature, more difficult. It's not uncommon to change too much lines of code because a requirement change is making our old assumptions about ownership obsolete due to how generics, lifetimes and async coexist.

But, in my experience, the biggest drawback of async is the fragmentation of the ecosystem. Now you have sync functions and libs, async functions and libs, and different runtimes that are incompatible and thus require dedicated libraries for I/O. When discussing with a friend who is into Python, he told me that they are experiencing the exact same problem and it creates a lot of busywork writing wrapper for sync code to be called by async code.

I think that, whether it be in Rust or in Python, async is the new (multi) Billion Dollar Mistake, where countless hours of developers' time is lost into the void.

When Rust makes sense

Despite all these flaws, there are a few usecases where Rust is the best tool available.

WebAssembly
As far as I know, today, Rust is the only programming language (with C) able to create efficient WebAssembly (wasm) libraries: no need to embed a big runtime or to use an over-complex compilation toolchain.

But WebAssembly is a new and immature technology and most projects don't actually need it.

Functional programming
While still having a syntax close to C++, Rust actually embraces a lot of ideas from functional programming such as immutability, iterators, combinators and pattern matching. If your problem is better solved with the functional paradigm (such as math heavy applications) then Rust may be more approachable than 'pure' functional languages.

When you work at insane scale
If you are AWS, Cloudflare, or building a next-gen database serving gazillions of transactions every seconds so you need to squeeze every byte of memory and microsecond of CPU time out of your servers, then Rust is a good fit providing you all the control you need while still allowing high-level abastractions.

Replacing C/C++/Assembly
But where Rust really shines is when replacing and / or interfacing with C / C++ projects.

The FFI (Foreign Function Interface) is a first class citizen, making C interfaces and wrappers easy and safe. It also makes embedding Rust into another language that supports C libraries a breeze which is actually done pretty often to embed a shared cross-platform core module on mobile and desktop applications across many Operating Systems.

Actually, modernizing a big and unsafe C++ codebase was the exact usecase that Rust was designed for. In January 2020, there was 2,219,891 lines of Rust in the Firefox browser (~7.8%) while in September 2023, there is now 3,431,530 (~9.6%) lines of Rust.

Starting a new project in a memory unsafe language in 2023 is a foolish endeavor, as demonstrated by the endless flow of vulnerabilities.

This is for this exact reason that today, Rust is the best programming language if you are working in IoT or Security where C or C++ codebases are common. It's a language filling all the needs of the field: embedded, shellcodes, cross-platform Remote Access Tools (RATs), reusable and embeddable exploits, scanners and more, replacing Assembly, C, C++ and more.

If you want to learn Rust, offensive security and cryptography, Go here.

1 email / week to learn how to (ab)use technology for fun & profit: Programming, Hacking & Entrepreneurship.
I hate spam even more than you do. I'll never share your email, and you can unsubscribe at any time.

Tags: golang, programming, rust

Want to learn Rust, Cryptography and Security? Get my book Black Hat Rust!