At The Daily Edit we have a small, sharp team that ships something new every single week. While there are many reasons for this cadence, one technical choice has helped immensely and that’s our choice to use Rust wherever we can. Rust enables us to achieve our company’s mission with speed and confidence.

When we started this project we were just three pilots. I was the only engineer of the group so I had complete freedom of choice in languages and tooling. This sounds nice in theory but it’s very daunting! Apart from the obvious use of Python for the machine learning parts everything else was open. Should we just choose Java since it’s boring? Should we choose Python because of the great community? Or should we do it all in Javascript since everything ends up in Javascript?

Every option has trade-offs so I was going in circles. What broke the infinite loop was one simple question: which choice would attract excellent hackers and allow us to ship something confidently frequently?

So here’s how we started using Rust and how today, even as the project matures, it continues to be a driver for our growth and success.

Background

Throughout my life I’ve worked and dabbled with a plethora of programming languages, editors, tools and methodologies. I got started back in 1994 messing around with QBasic and the Gorillas game that came with MS-DOS. Soon after I got into C and worked almost entirely on unix platforms. Then C++, Python, PHP, Ruby and of course JavaScript a bit later. Some of these usages were for fun especially when I was younger, some were for profit during my later teen years and early 20s. Then I started flying planes and the programming was all just for fun. 

In 2015 I started messing around with Rust after having heard about it from a PLT friend. She kept saying that it brought the first truly ‘new’ thing to PLT in a long time, that thing being lifetimes in the syntax. I was fairly skeptical and, like many others, accepted that C was the best systems language since it was so simple and easy to reason about.

Until I started using Rust.

My skepticism faded very quickly when I realized that despite my experience and best intentions, I was in fact making mistakes with C. Subtle leaks, use-after-free, they don’t really happen when everything’s nice and small and self-contained, but when you start making and using libraries and passing pointers to opaque structs around it gets messy. Rust made it very clear that I was not the programmer I thought I was. The compiler was like a crusty old simulator instructor where no matter how well you did something, it was never enough. I hit the ‘fighting the borrow checker’ phase like hitting my toe on the corner of a wall, persistent pain and a feeling of being broken.

But that passed, reasonably quickly.

It took about 3 months of using Rust before I really became comfortable with it. Toy projects didn’t cut it. Once I started working on more complex systems such as a distributed job queue with asynchronous behavior or an embedded system interfacing with an FPGA, the gains started to come. It’s like working out, you really have to push it to get the benefit. After these projects I didn’t run into the nagging compiler as much and the organization of the code started to become clear very early on into any project. That’s the thing with Rust, it can be annoying but it really guides you towards an excellent architecture.

But that’s not the best part.

The best part is that once you’ve built this big, complex system and pleased the compiler enough for it to give you a binary. It just works. And continues working. The amount of debugging required for Rust projects is an order of magnitude less than I’ve seen anywhere else. With features like tagged unions (Rust’s enum) the exact working of the code can be specified clearly and inviolably. This gives extreme confidence when deploying anything. Then comes the regular change and maintenance that any project has. Often, an engineer new to the company will have to dive into some code they haven’t seen before. With Rust, that on-ramp has guard rails. If they interact with the existing code in an unexpected way, the compiler tells them.

Attracting talent

Rust has entered the popular use phase of its time, there are almost as many blog posts singing its praises as there are exposing its shortcomings. That’s a great sign, it means that it’s being used. It’s no surprise I like Rust but what about other engineers? One of our main concerns with selecting a relatively niche language like Rust was that the size of the talent pool might be too small. The thing is, the really world-class talent out there care about the ideas they get to work on *and* the tools they get to work with.

The time came to reach out and test the water. We contacted the This Week in Rust newsletter and had our job listings placed there. We’re a remote-first company and don’t care where our engineers choose to live. By a great stroke of luck Twitter’s Jack Dorsey tweeted that “rust is a perfect programming language”.

Over the next eight weeks I received emails from almost four thousand applicants. Four thousand! Many didn’t actually have Rust experience at all and that’s fine, they were just interested in the idea. We were spoiled for choice and have found ourselves with nothing short of a world-class engineering team.

Our concerns about the talent pool for Rust were unnecessary. It’s a language that attracts experienced programmers who want to deliver.

Getting things done

We use Rust everywhere we can. Right now our web backend is built in Rust, our background task processors are in Rust, the scheduler for our analysis engine? You guessed it, Rust. The only places we don’t use it are those which have an incredible library that doesn’t yet exist in Rust’s ecosystem. Also the mobile app, there we use Flutter.

One of the shortcomings Rust is often reported of having is a rather verbose syntax that takes a long time to both write and read. While parts of this are true (it’s a lot more verbose than Python), many are exaggerated. For example, across our entire codebase we have manually annotated lifetimes fewer than a dozen times. It just doesn’t come up that often in application code.

With Rust there is more work required up-front. You do need to please the compiler across a large number of constraints. However, the cognitive overhead of this, and the time required to actually write it, diminishes very rapidly with a little experience. Over the course of just a few weeks, with the myriad changes that a startup goes through in that time, it requires less work. Far less. Our team all agree that reading Rust code is simpler than many other languages. There’s no doubt or ambiguity of any kind, you know exactly what the program is going to do by reading it.

We operate with a very small team of talented engineers and iterate on code at rapid speed. With Rust we can decide to rewrite an entire, complicated, module and have confidence that after it compiles it will work just fine. Sometimes we make errors with our logic or our understanding of the problem isn’t quite right, no language will prevent that, but for every other task that’s required to get something into production, Rust lets us do it faster.

With Rust you can go very far with very few engineers.

Performance

No post about Rust would be complete without this but it’s well known so I’ll keep it brief. Rust is fast. Most of the pain people write about with lifetimes goes away if you just use a `clone` or `Arc` here or there, and guess what, it’s still orders of magnitude faster than Python, Ruby, Javascript and Java. Then if it really becomes necessary to squeeze that last drop of performance out of it, you can write out those complex lifetimes. It’s nice to write something easily and have truly excellent performance but know that the ceiling on that performance is still higher.

What does this have to do with startups though? Well, high performance means fewer servers, fewer servers means less operational overhead. As a startup your runway burns up pretty fast if you start spending it on web servers that can only support a few hundred requests per second each.

The usual trope brought out to fight my argument would be “engineer time is more expensive than computer time” and that is true. But you really don’t need much more engineer time than using another language, and you get the lower overhead when you actually run your program. 

It pays itself off very quickly.

Should your startup use it?

I’m not a startup adviser.

I began by writing that choosing a language for a greenfield startup can be daunting, more so when the language you think best fits is a bit niche and new. From our team’s experience with Rust so far, we don’t want to use anything else. It may be hard to learn but the return on that investment is incredible. 

In the hands of an experienced team Rust is a superpower.

In the next post we’ll go into some of the downsides of using Rust.