We migrated to Rust, but what did we gain?

ByteBaker
5 min readDec 26, 2022

--

We chose Rust as the programming language for our next project, and it didn’t disappoint.

The backstory

I work as a backend dev for a healthcare-centric software company. For most part, we use Python as the backbone of our software stack. The product that I work on involves lots of computation and transformation, processing anything from a several thousand to a million JSON rows per request-response cycle.

Originally written in Python using FastAPI, at some point it started hitting its speed limit. The typical round-trip time (RTT) would be anywhere between 5 seconds for the best case, to over a minute in the worst.

It was then that we decided to give Rust a shot. Although the web frameworks in Rust were still not as mature as the ones in Python (or many other languages), and we didn’t have a workforce well-versed in Rust, we chose to bite the proverbial bullet.

Once we were ready with equivalent code flow in Rust, we were eventually able to achieve an RTT of anything shy of a second to less than 10 seconds for the best to worst case respectively. Thus, choosing Rust was a risk, but it paid well. And 18 months later, we’re more than just happy that we did.

The most obvious reasons for the switch

It’s fast (duh).

Speed comparison of various programming languages

As you can see above, Rust performs almost at par with C and C++ in terms of performance, while CPython (which most of us use) is just north of the last spot, despite being in great use. You can read further here, the results are updated from time to time.

You might recall this table from a paper published by Pereira, et al.

Only second to C, Rust tops both energy efficiency and speed. Both of these manifest themselves in form of lower infrastructure cost for us, whether its our own or on the cloud.

But then we could’ve just used C or C++, no?

First of all, we wanted to create a web application. The question is, if not for some esoteric weekend project, who really would build a web app in those languages? Not to mention the amount of boilerplate and abstractions that they’d have to write just to avoid repeating a lot of stuff is mind boggling.

But here’s the juice of the matter. Both C and C++ have a problem that many other languages tried solving, but couldn’t, at least not without a garbage collector. It was memory safety. In simple words, memory safety means that every memory address that a variable points to must exist and contain the implied value.

In fact, Tony Hoare called the creation of Null Pointers as the Billion Dollar Mistake. The lack of memory safety is responsible for a lot of bugs and security vulnerabilities in applications, and even though in theory it’s possible to write memory-safe code by hand, we’re humans after all.

The USP that Rust comes with is the guarantee to be memory safe at compile time. Rust has a mechanism called the Borrow Checker that takes care of it, which is beyond the scope of this article (but it’s really cool, I promise).

The fact that Rust doesn’t have a garbage collector, coupled with its static type system (which makes the code so very understandable), with the extremely elegant (and modern) syntax made it an excellent choice for our purposes.

Ease of shipping and deployment (plus code ownership)

One great challenge that we had to face with our past deployments in Python was how we handled the code. There were multiple files in a specific hierarchical structure that we had to maintain inside the deployment environment.

Then there was the issue of who has access to our code. If the deployment environment was owned by a customer, they essentially have access to our proprietary code as well. And even compiled Python bytecode can easily be decompiled. So there’s that.

Add problems like versioning and runtime maintenance, and the problem quickly becomes humongous. People familiar with Java know how much of a pain can it be.

Rust solves all these problems just by being an assembly-compiled language. It compiles directly to assembly, removing both code shipping and ownership problems in a single shot.

The sheer convenience of writing code

There’s a general trend when it comes to choosing the right tool for a job. Usually, simpler tools are easy to learn, but get harder to achieve more sophisticated tasks, whereas the exact opposite is true for sophisticated tools, which have a steeper learning curve, but get more convenient over time.

The same applies to Rust as well. It forces you to do certain things from the get-go. Such as making sure that you name your variables and functions in snake_case, remove unused imports, variables, and functions etc.

fn main() {
let fooCount = 11;
}

For example, above code snippet generates a compiler warning.

warning: unused variable: `fooCount`
--> src\main.rs:2:9
|
2 | let fooCount = 11;
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_fooCount`
|
= note: `#[warn(unused_variables)]` on by default

warning: variable `fooCount` should have a snake case name
--> src\main.rs:2:9
|
2 | let fooCount = 11;
| ^^^^^^^^ help: convert the identifier to snake case: `foo_count`
|
= note: `#[warn(non_snake_case)]` on by default

Yes! A compiler warning. It’s not an extra tool you need to check your code but the compiler itself is doing it for you.

And did you notice the extremely helpful messages? Including suggestions on how to fix the issue. Well that’s just one of the countless beautiful things about Rust that’ll make you fall in love with it more and more.

So, where to now?

Much as I’d love to talk about Rust the entire day, the reasons to use it are endless (I even left out the macros). When you have to choose between performance, efficiency, memory-safety, a powerful package manager, an amazing linting tool (that’s also builtin), and modern syntax, why not choose everything? Why not choose Rust?

Don’t trust me, no hard feelings, but perhaps the developers who voted Rust as the most loved programming language for the 7th year in a row might convince you.

Till then, happy coding!

--

--