Overview
Rocket (2016) was the first Rust web framework with a real developer-experience thesis: routing as attribute macros, request validation as types, sensible defaults, "it should feel like Rails, but checked at compile time". For years it was also the framework that required nightly — its macros leaned on unstable features — which cost it the momentum axum later captured. Rocket 0.5 (2023) landed the rebirth: stable Rust, fully async on Tokio, hyper underneath. It remains the most ergonomic entry point in the ecosystem, with a smaller community and slower cadence than the two leaders.
Key points
- Routing is declarative:
#[get("/users/<id>?<page>")]binds path segments and query params straight into typed function arguments; unmatched types simply don't route (forwarding), turning 404-vs-422 semantics into the type system's job. - Request guards are the signature idea: any argument implementing
FromRequest— anAdminUserguard that validates the session, aDbConn— runs before the handler; auth as types rather than middleware ordering. - Fairings are the lifecycle hooks (attach, request, response) — deliberately not a middleware chain; less composable than tower, simpler to reason about.
- Batteries included: typed multi-profile config (
Rocket.toml+ROCKET_-prefixed env vars), forms with derived validation, templating (Tera and Handlebars viarocket_dyn_templates), TLS,rocket_db_poolsfor sqlx/deadpool integration. - Responders mirror guards:
#[derive(Responder)]on enums for typed success/error responses;Result<Json<T>, Status>for the quick path. - The trade: highest ergonomics per line and the gentlest learning curve, at the cost of macro-heavy indirection (attribute magic is what axum explicitly avoided), a one-core-team bus factor, and an ecosystem that mostly targets tower now — Rocket integrations are Rocket-specific, the Jakarta-vs-stdlib question in miniature.
- When it wins: self-contained applications where DX and onboarding dominate — internal tools, teaching, small products; less so services that want deep tower/OpenTelemetry/gRPC ecosystem interop.
Examples
#[get("/users/<id>")]
async fn show_user(id: Uuid, _admin: AdminUser, db: &State<Pool>) -> Result<Json<User>, Status> {
users::find(db, id).await.map(Json).map_err(|_| Status::NotFound)
}
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(Db::init()) // fairing
.mount("/api", routes![show_user])
}
Related
- Rust web frameworks — the landscape — parent overview.
- Frameworks × tower/hyper — Rocket's hybrid position on the substrate.
- Axum deep dive — the macro-free counterpoint that won the default slot.
- Spring deep dive — the convention-and-ergonomics ancestor of the genre, one ecosystem over.