Rust + Axum Backend Mastery
Production-ready patterns for building scalable Rust backends with Axum and PostgreSQL.
When to Use This Skill
- Building REST APIs or GraphQL with Axum
- Designing database schemas with SQLx + PostgreSQL
- Implementing authentication (JWT, OAuth 2.1)
- Writing async code with Tokio
- Creating middleware and extractors
- Testing Axum applications
- Deploying to production (Docker, Kubernetes)
- Performance optimization and monitoring
Quick Start
Minimal Axum Server
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(|| async { "Hello, Axum!" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Essential Dependencies (Cargo.toml)
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
tower = "0.4"
tower-http = { version = "0.5", features = ["cors", "trace"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "uuid", "time"] }
uuid = { version = "1", features = ["v4", "serde"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
thiserror = "1"
anyhow = "1"
Reference Navigation
Core Rust Patterns
| Topic |
File |
Description |
| Rust Idioms |
rust-patterns.md |
Enums, iterators, error handling |
| Async/Tokio |
async-tokio.md |
Async patterns, spawn, channels |
Axum Framework (70%)
| Topic |
File |
Description |
| Axum Guide |
axum-complete-guide.md |
Routing, handlers, state |
| Extractors |
axum-extractors.md |
Path, Query, Json, State |
| Middleware |
middleware-patterns.md |
Tower layers, auth middleware |
Database (PostgreSQL)
| Topic |
File |
Description |
| SQLx |
sqlx-postgresql.md |
Queries, transactions, migrations |
| Patterns |
database-patterns.md |
Connection pools, optimization |
Architecture
| Topic |
File |
Description |
| Project Structure |
project-structure.md |
Folder organization |
| Patterns |
architecture-patterns.md |
Microservices, modulith |
Security & Auth
| Topic |
File |
Description |
| Authentication |
authentication.md |
JWT, OAuth 2.1, sessions |
| Security |
security-owasp.md |
OWASP Top 10 for Rust |
Testing & Quality
| Topic |
File |
Description |
| Testing |
testing-guide.md |
Unit, integration, E2E |
| Error Handling |
error-handling.md |
HTTP errors, thiserror |
DevOps & Production
| Topic |
File |
Description |
| Deployment |
deployment.md |
Docker, Kubernetes |
| Monitoring |
monitoring.md |
Tracing, Prometheus |
Decision Guide
When to Choose Axum (70% - Primary)
✅ Choose Axum when:
- Building new Rust web projects
- Need tower ecosystem compatibility
- Want ergonomic, type-safe extractors
- Prefer modular, composable design
- Need excellent async performance
When to Consider Alternatives (30%)
Actix-web - When you need:
- Maximum raw performance (benchmarks leader)
- Actor model for complex state
- Established ecosystem with more examples
Rocket - When you need:
- Simplest learning curve
- Most "magical" developer experience
- Rapid prototyping
Core Patterns Summary
Error Handling
use axum::{http::StatusCode, response::IntoResponse, Json};
use serde_json::json;
pub enum AppError {
NotFound(String),
Database(sqlx::Error),
Unauthorized,
}
impl IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
Self::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
Self::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
Self::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".into()),
};
(status, Json(json!({ "error": message }))).into_response()
}
}
Handler Pattern
use axum::{extract::{Path, State}, Json};
use uuid::Uuid;
async fn get_user(
State(pool): State<PgPool>,
Path(id): Path<Uuid>,
) -> Result<Json<User>, AppError> {
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&pool)
.await?
.ok_or_else(|| AppError::NotFound("User not found".into()))?;
Ok(Json(user))
}
State Management
use std::sync::Arc;
use sqlx::PgPool;
#[derive(Clone)]
pub struct AppState {
pub db: PgPool,
pub config: Arc<Config>,
}
let app = Router::new()
.route("/users/:id", get(get_user))
.with_state(AppState { db: pool, config: Arc::new(config) });
Examples
- axum-starter - Minimal project template
- axum-rest-api - Complete REST API with auth
Best Practices Checklist
API Design
Database
Security
Testing
Production
Resources
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: rust-backend-advance3description: Production-ready Rust backend development with Axum framework and PostgreSQL. Master async patterns, tower middleware, SQLx database operations, authentication (JWT/OAuth), testing strategies, and deployment. Use when building REST APIs, microservices, or any Rust web backend with Axum. Use when this capability is needed.4---56# Rust + Axum Backend Mastery78Production-ready patterns for building scalable Rust backends with Axum and PostgreSQL.910## When to Use This Skill1112- Building REST APIs or GraphQL with Axum13- Designing database schemas with SQLx + PostgreSQL14- Implementing authentication (JWT, OAuth 2.1)15- Writing async code with Tokio16- Creating middleware and extractors17- Testing Axum applications18- Deploying to production (Docker, Kubernetes)19- Performance optimization and monitoring2021---2223## Quick Start2425### Minimal Axum Server2627```rust28use axum::{routing::get, Router};2930#[tokio::main]31async fn main() {32 let app = Router::new()33 .route("/", get(|| async { "Hello, Axum!" }));3435 let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();36 axum::serve(listener, app).await.unwrap();37}38```3940### Essential Dependencies (Cargo.toml)4142```toml43[dependencies]44axum = "0.7"45tokio = { version = "1", features = ["full"] }46tower = "0.4"47tower-http = { version = "0.5", features = ["cors", "trace"] }48serde = { version = "1", features = ["derive"] }49serde_json = "1"50sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "uuid", "time"] }51uuid = { version = "1", features = ["v4", "serde"] }52tracing = "0.1"53tracing-subscriber = { version = "0.3", features = ["env-filter"] }54thiserror = "1"55anyhow = "1"56```5758---5960## Reference Navigation6162### Core Rust Patterns63| Topic | File | Description |64|-------|------|-------------|65| Rust Idioms | [rust-patterns.md](references/rust-patterns.md) | Enums, iterators, error handling |66| Async/Tokio | [async-tokio.md](references/async-tokio.md) | Async patterns, spawn, channels |6768### Axum Framework (70%)69| Topic | File | Description |70|-------|------|-------------|71| **Axum Guide** | [axum-complete-guide.md](references/axum-complete-guide.md) | Routing, handlers, state |72| Extractors | [axum-extractors.md](references/axum-extractors.md) | Path, Query, Json, State |73| Middleware | [middleware-patterns.md](references/middleware-patterns.md) | Tower layers, auth middleware |7475### Database (PostgreSQL)76| Topic | File | Description |77|-------|------|-------------|78| SQLx | [sqlx-postgresql.md](references/sqlx-postgresql.md) | Queries, transactions, migrations |79| Patterns | [database-patterns.md](references/database-patterns.md) | Connection pools, optimization |8081### Architecture82| Topic | File | Description |83|-------|------|-------------|84| Project Structure | [project-structure.md](references/project-structure.md) | Folder organization |85| Patterns | [architecture-patterns.md](references/architecture-patterns.md) | Microservices, modulith |8687### Security & Auth88| Topic | File | Description |89|-------|------|-------------|90| Authentication | [authentication.md](references/authentication.md) | JWT, OAuth 2.1, sessions |91| Security | [security-owasp.md](references/security-owasp.md) | OWASP Top 10 for Rust |9293### Testing & Quality94| Topic | File | Description |95|-------|------|-------------|96| Testing | [testing-guide.md](references/testing-guide.md) | Unit, integration, E2E |97| Error Handling | [error-handling.md](references/error-handling.md) | HTTP errors, thiserror |9899### DevOps & Production100| Topic | File | Description |101|-------|------|-------------|102| Deployment | [deployment.md](references/deployment.md) | Docker, Kubernetes |103| Monitoring | [monitoring.md](references/monitoring.md) | Tracing, Prometheus |104105---106107## Decision Guide108109### When to Choose Axum (70% - Primary)110111```112✅ Choose Axum when:113- Building new Rust web projects114- Need tower ecosystem compatibility115- Want ergonomic, type-safe extractors116- Prefer modular, composable design117- Need excellent async performance118```119120### When to Consider Alternatives (30%)121122```123Actix-web - When you need:124- Maximum raw performance (benchmarks leader)125- Actor model for complex state126- Established ecosystem with more examples127128Rocket - When you need:129- Simplest learning curve130- Most "magical" developer experience131- Rapid prototyping132```133134---135136## Core Patterns Summary137138### Error Handling139```rust140use axum::{http::StatusCode, response::IntoResponse, Json};141use serde_json::json;142143pub enum AppError {144 NotFound(String),145 Database(sqlx::Error),146 Unauthorized,147}148149impl IntoResponse for AppError {150 fn into_response(self) -> axum::response::Response {151 let (status, message) = match self {152 Self::NotFound(msg) => (StatusCode::NOT_FOUND, msg),153 Self::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),154 Self::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".into()),155 };156 (status, Json(json!({ "error": message }))).into_response()157 }158}159```160161### Handler Pattern162```rust163use axum::{extract::{Path, State}, Json};164use uuid::Uuid;165166async fn get_user(167 State(pool): State<PgPool>,168 Path(id): Path<Uuid>,169) -> Result<Json<User>, AppError> {170 let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)171 .fetch_optional(&pool)172 .await?173 .ok_or_else(|| AppError::NotFound("User not found".into()))?;174 175 Ok(Json(user))176}177```178179### State Management180```rust181use std::sync::Arc;182use sqlx::PgPool;183184#[derive(Clone)]185pub struct AppState {186 pub db: PgPool,187 pub config: Arc<Config>,188}189190let app = Router::new()191 .route("/users/:id", get(get_user))192 .with_state(AppState { db: pool, config: Arc::new(config) });193```194195---196197## Examples198199- **[axum-starter](examples/axum-starter/)** - Minimal project template200- **[axum-rest-api](examples/axum-rest-api/)** - Complete REST API with auth201202---203204## Best Practices Checklist205206### API Design207- [ ] Use proper HTTP methods (GET, POST, PUT, DELETE)208- [ ] Return appropriate status codes209- [ ] Validate input with extractors210- [ ] Document with OpenAPI/Swagger211212### Database213- [ ] Use connection pooling (SQLx built-in)214- [ ] Always use parameterized queries215- [ ] List columns explicitly (no SELECT *)216- [ ] Use transactions for multi-step operations217218### Security219- [ ] Validate all input220- [ ] Use Argon2id for passwords221- [ ] Implement rate limiting222- [ ] Set security headers (tower-http)223224### Testing225- [ ] Unit tests for business logic226- [ ] Integration tests for handlers227- [ ] Use testcontainers for database tests228229### Production230- [ ] Structured logging (tracing)231- [ ] Health check endpoints232- [ ] Graceful shutdown233- [ ] Docker multi-stage builds234235---236237## Resources238239- **Axum**: https://docs.rs/axum240- **Tower**: https://docs.rs/tower241- **SQLx**: https://docs.rs/sqlx242- **Tokio**: https://tokio.rs243244---245> Converted and distributed by [TomeVault](https://tomevault.io/claim/thienty1207) — claim your Tome and manage your conversions.246<!-- tomevault:4.0:skill_md:2026-04-15 -->