Why Rust for the Backend?
You've heard the pitch. Memory safety without garbage collection. Fearless concurrency. Zero-cost abstractions. It compiles, therefore it works. Et cetera.
All of that is true, and none of it is why you should write your backend in Rust.
You should write your backend in Rust because the ecosystem has finally caught up to the language. For years, Rust had the best type system in production use and an async story that required reading several blog posts, a few RFCs, and at least one existential crisis to understand. That era is over. Tokio is stable and excellent. Axum is ergonomic and fast. SQLx gives you compile-time checked SQL queries. The toolchain is genuinely good.
This book is about building real backend services — HTTP APIs, database access, authentication, observability, deployment — using the current stable Rust ecosystem. We're not going to implement a toy JSON API that returns { "hello": "world" } and call it a day. We're going to build things that work in production.
What This Book Is Not
This is not a Rust tutorial. If you need to be told what a lifetime is, start with The Rust Programming Language and come back. We'll be here.
This is not a survey of every async runtime or HTTP framework. Tokio runs the world. Axum is built on Tower and Hyper, which are the best abstractions available. We're going to learn these tools deeply rather than skimming ten alternatives.
This is not a book about microservices architecture, Kubernetes, or why you should decompose your monolith. Those are fine topics. They're not this topic.
What This Book Is
A practical guide to the choices that actually matter:
- Which crate, and why — not "here are five options, pick one"
- What the type system is telling you — Axum's extractor pattern is elegant once you understand
FromRequest, confusing until you do - How things fail in production — error handling, connection pools, panics in async tasks
- How to know what's happening — structured logging, distributed tracing, metrics
- How to ship it — containers, static binaries, multi-stage Docker builds
The Stack
Throughout this book, we'll use:
| Concern | Crate | Version |
|---|---|---|
| Async runtime | tokio | 1.x |
| HTTP framework | axum | 0.7.x |
| Database | sqlx | 0.7.x |
| Middleware | tower / tower-http | 0.5.x / 0.5.x |
| Tracing | tracing / tracing-subscriber | 0.1.x |
| Error handling | thiserror / anyhow | 1.x |
| Configuration | config + dotenvy | 0.14.x / 0.15.x |
| JWT | jsonwebtoken | 9.x |
These are not the only options. They are good options, they work together, and they're what you'll encounter in real Rust backend codebases today.
A Note on Cargo Editions and MSRV
All examples in this book use the 2021 edition. Your Cargo.toml should have:
[package]
edition = "2021"
We'll target Rust 1.75+, which is when async fn in traits was stabilized. Some patterns in this book require it.
Getting Started
If you don't have Rust installed:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Then install the stable toolchain:
rustup default stable
rustup update
Verify:
rustc --version # rustc 1.75.0 or newer
cargo --version
We'll create a new project at the start of each major chapter. When you're ready to follow along for real, run:
cargo new --bin my-backend
cd my-backend
Now let's talk about async.