Building a microservice with Rust

Mikhail Medvedev
Feb 17 · 5 min read

Can you build a microservice using Rust? Or more importantly, should you?

Photo by Aaron Chavez on Unsplash

While Kotlin and Python are the dominant languages in Tenable we do dedicate time to investigate what emerging technologies are worth considering for our tech stack. Rust is one of them. It has proved itself as a powerful instrument and a great replacement for older, memory error-prone languages like C. Rust is expressive, modern and provides excellent tooling. But the most remarkable feature is, of course, its innovative ownership model that can prevent most memory-related bugs at compile-time, and without a garbage collector.

Also, we develop and maintain a range of microservice oriented architectures. Love them or hate them, microservices are extremely useful for building scalable and resilient applications.

Traditionally, teams develop microservices using languages like Java or Python and benefit from their ecosystems. You can just google “Java microservice” or “Python microservice” to find dozens of recipes on how to do that.

Can you build a microservice using Rust, though? Or more importantly, should you?

We decided to run an experiment and create a simple microservice written in Rust to see for ourselves if it’s worth it. The thinking was: if we failed, we would learn something useful anyway, if we succeeded, we would add a new awesome device to our team’s toolbox.

Pieces of the puzzle

  • HTTP API: most microservices will have to provide a REST API. At the very least a service should be able to respond to basic health check requests from a larger management service.
  • Code to work with the database: usually some form of an ORM.
  • Code to read messages from a queue, such as Kafka.
  • A Dockerfile to build the service so it could be deployed (e.g. to Kubernetes).

That’s what we need to put together a microservice, regardless of the language used. For Java or Python, these points are relatively well-researched and a few time-proven libraries are available. For Rust, as a newer language, we needed to find and choose the crates, and then write code to glue them together.

Rust project

mkdir service_rust && cd service_rust
cargo init

This creates two files: Cargo.toml which holds various project metadata, and src/main.rs that is the entry point of our code. The program starts with running the main() function.

That’s very easy to compile and run:

cargo run

Web API

After some research, we narrowed the list down to Actix-web, Rocket, and Warp.

We eventually chose Actix-web: it is popular, easy to use, has all the features and comes together with the Actor system library which we could use for a Kafka consumer thread.

The syntax somewhat resembles Flask and integrates with our main() function:

Database client

Kafka consumer

Here we run a Kafka processor in a thread parallel to the API:

Serialization/deserialization of JSON is handled seamlessly by Serde, which is another amazing feature of Rust.

Dockerfile

Now, I have to admit: this doesn’t work. It builds the image, but if we try to run it, it will crash with an error message something like this:

standard_init_linux.go:219: exec user process caused: no such file or directory

The reason is that some Rust crates depend on external libraries. In order to make them work, we’ll have to either install them on the resulting image or build them statically into our binary. To implement the latter, we can use a custom “builder” image, for example, rust-musl-builder (https://github.com/emk/rust-musl-builder):

Now the service builds and even runs.

What isn’t covered

  • Testing: Rust features a built-in unit testing facility. Just try it — it’s amazing.
  • Configuration: this is trivial to implement, but at the same time, very environment-specific.
  • Logging: it is pretty straightforward.
  • SSL: although we touched on this with regards to the building stage, usually you also have to deal with certificates and openssl initialisation code. However, exploring this topic may require another full-sized article.
  • Other things that are specific to our environment.

In conclusion

However, in a limited period of time, we built a service that is ready to be shipped, doesn’t need any web or application server, and features advanced functionality like asynchronous execution — that is very encouraging.

A microservice made with Rust has a few distinctive advantages:

  • It enjoys great performance compared to traditional alternatives.
  • It is free from most of the memory-related bugs which plague lower-level languages.
  • It takes advantage of a powerful type system of Rust: many bugs can be caught at compile time.
  • It requires no additional runtime (the runtime is compiled into a binary that is easily shipped.)
  • This binary doesn’t run a garbage collector. This makes it easier to control the resources utilized by the service.

We must mention the downsides as well:

  • Rust has a steeper learning curve than Python or Java.
  • It is also a relatively new language, so the ecosystem isn’t so established.
  • The community, as welcoming as it is, is also significantly smaller.

Rust is an extremely useful tool in building reliable and performant architectures. Even though it’s still a relatively new technology, the results are promising. It’s definitely worth it to have it in your toolbox.

Tenable TechBlog

Learn how Tenable finds new vulnerabilities and writes the…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store