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
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.4license: MIT5---67# Rust + Axum Backend Mastery89Production-ready patterns for building scalable Rust backends with Axum and PostgreSQL.1011## When to Use This Skill1213- Building REST APIs or GraphQL with Axum14- Designing database schemas with SQLx + PostgreSQL15- Implementing authentication (JWT, OAuth 2.1)16- Writing async code with Tokio17- Creating middleware and extractors18- Testing Axum applications19- Deploying to production (Docker, Kubernetes)20- Performance optimization and monitoring2122---2324## Quick Start2526### Minimal Axum Server2728```rust29use axum::{routing::get, Router};3031#[tokio::main]32async fn main() {33 let app = Router::new()34 .route("/", get(|| async { "Hello, Axum!" }));3536 let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();37 axum::serve(listener, app).await.unwrap();38}39```4041### Essential Dependencies (Cargo.toml)4243```toml44[dependencies]45axum = "0.7"46tokio = { version = "1", features = ["full"] }47tower = "0.4"48tower-http = { version = "0.5", features = ["cors", "trace"] }49serde = { version = "1", features = ["derive"] }50serde_json = "1"51sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "uuid", "time"] }52uuid = { version = "1", features = ["v4", "serde"] }53tracing = "0.1"54tracing-subscriber = { version = "0.3", features = ["env-filter"] }55thiserror = "1"56anyhow = "1"57```5859---6061## Reference Navigation6263### Core Rust Patterns64| Topic | File | Description |65|-------|------|-------------|66| Rust Idioms | [rust-patterns.md](references/rust-patterns.md) | Enums, iterators, error handling |67| Async/Tokio | [async-tokio.md](references/async-tokio.md) | Async patterns, spawn, channels |6869### Axum Framework (70%)70| Topic | File | Description |71|-------|------|-------------|72| **Axum Guide** | [axum-complete-guide.md](references/axum-complete-guide.md) | Routing, handlers, state |73| Extractors | [axum-extractors.md](references/axum-extractors.md) | Path, Query, Json, State |74| Middleware | [middleware-patterns.md](references/middleware-patterns.md) | Tower layers, auth middleware |7576### Database (PostgreSQL)77| Topic | File | Description |78|-------|------|-------------|79| SQLx | [sqlx-postgresql.md](references/sqlx-postgresql.md) | Queries, transactions, migrations |80| Patterns | [database-patterns.md](references/database-patterns.md) | Connection pools, optimization |8182### Architecture83| Topic | File | Description |84|-------|------|-------------|85| Project Structure | [project-structure.md](references/project-structure.md) | Folder organization |86| Patterns | [architecture-patterns.md](references/architecture-patterns.md) | Microservices, modulith |8788### Security & Auth89| Topic | File | Description |90|-------|------|-------------|91| Authentication | [authentication.md](references/authentication.md) | JWT, OAuth 2.1, sessions |92| Security | [security-owasp.md](references/security-owasp.md) | OWASP Top 10 for Rust |9394### Testing & Quality95| Topic | File | Description |96|-------|------|-------------|97| Testing | [testing-guide.md](references/testing-guide.md) | Unit, integration, E2E |98| Error Handling | [error-handling.md](references/error-handling.md) | HTTP errors, thiserror |99100### DevOps & Production101| Topic | File | Description |102|-------|------|-------------|103| Deployment | [deployment.md](references/deployment.md) | Docker, Kubernetes |104| Monitoring | [monitoring.md](references/monitoring.md) | Tracing, Prometheus |105106---107108## Decision Guide109110### When to Choose Axum (70% - Primary)111112```113✅ Choose Axum when:114- Building new Rust web projects115- Need tower ecosystem compatibility116- Want ergonomic, type-safe extractors117- Prefer modular, composable design118- Need excellent async performance119```120121### When to Consider Alternatives (30%)122123```124Actix-web - When you need:125- Maximum raw performance (benchmarks leader)126- Actor model for complex state127- Established ecosystem with more examples128129Rocket - When you need:130- Simplest learning curve131- Most "magical" developer experience132- Rapid prototyping133```134135---136137## Core Patterns Summary138139### Error Handling140```rust141use axum::{http::StatusCode, response::IntoResponse, Json};142use serde_json::json;143144pub enum AppError {145 NotFound(String),146 Database(sqlx::Error),147 Unauthorized,148}149150impl IntoResponse for AppError {151 fn into_response(self) -> axum::response::Response {152 let (status, message) = match self {153 Self::NotFound(msg) => (StatusCode::NOT_FOUND, msg),154 Self::Database(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),155 Self::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".into()),156 };157 (status, Json(json!({ "error": message }))).into_response()158 }159}160```161162### Handler Pattern163```rust164use axum::{extract::{Path, State}, Json};165use uuid::Uuid;166167async fn get_user(168 State(pool): State<PgPool>,169 Path(id): Path<Uuid>,170) -> Result<Json<User>, AppError> {171 let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)172 .fetch_optional(&pool)173 .await?174 .ok_or_else(|| AppError::NotFound("User not found".into()))?;175 176 Ok(Json(user))177}178```179180### State Management181```rust182use std::sync::Arc;183use sqlx::PgPool;184185#[derive(Clone)]186pub struct AppState {187 pub db: PgPool,188 pub config: Arc<Config>,189}190191let app = Router::new()192 .route("/users/:id", get(get_user))193 .with_state(AppState { db: pool, config: Arc::new(config) });194```195196---197198## Examples199200- **[axum-starter](examples/axum-starter/)** - Minimal project template201- **[axum-rest-api](examples/axum-rest-api/)** - Complete REST API with auth202203---204205## Best Practices Checklist206207### API Design208- [ ] Use proper HTTP methods (GET, POST, PUT, DELETE)209- [ ] Return appropriate status codes210- [ ] Validate input with extractors211- [ ] Document with OpenAPI/Swagger212213### Database214- [ ] Use connection pooling (SQLx built-in)215- [ ] Always use parameterized queries216- [ ] List columns explicitly (no SELECT *)217- [ ] Use transactions for multi-step operations218219### Security220- [ ] Validate all input221- [ ] Use Argon2id for passwords222- [ ] Implement rate limiting223- [ ] Set security headers (tower-http)224225### Testing226- [ ] Unit tests for business logic227- [ ] Integration tests for handlers228- [ ] Use testcontainers for database tests229230### Production231- [ ] Structured logging (tracing)232- [ ] Health check endpoints233- [ ] Graceful shutdown234- [ ] Docker multi-stage builds235236---237238## Resources239240- **Axum**: https://docs.rs/axum241- **Tower**: https://docs.rs/tower242- **SQLx**: https://docs.rs/sqlx243- **Tokio**: https://tokio.rs