Axeon 1.0 is here

The Rust web framework that feels like Express.

Write handlers as simply as in Express and get Rust's speed, memory efficiency and safety. Built on hyper, batteries included, and ready for production.

$ cargo add axeon
src/main.rs
use axeon::Server;

fn main() {
    let mut app = Server::new();
    app.get("/", |_req| async { "Hello, World!" });
    app.listen("127.0.0.1:3000")
        .expect("server failed to start");
}
Terminal
$ cargo run
$ curl -i http://127.0.0.1:3000/
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8

Hello, World!
176kJSON requests per second
8.9 MiBmemory under load
4–5×the throughput of Express
2 msp99 latency

Apple M1, 128 keep-alive connections, best of three runs. Methodology and caveats.

Everything a backend needs

Small surface, no surprises. The pieces you reach for in every project are already there and already secure.

Simple by design

Express-like routing and middleware. Handlers return plain values: text, Json(..), (201, body), Option or Result.

Fast and lean

Within ~10% of the fastest Rust frameworks, at about 4–5× Express throughput on 1/100th of the memory. Routing time doesn't grow with route count.

Batteries included

Validation, JWT, cookies, sessions, CSRF, typed config, templates, static files, uploads, server-sent events and WebSockets.

Secure by default

Size limits, timeouts, slow-client protection, security headers, rate limiting, CORS, panic isolation and constant-time secret comparison.

Production ready

HTTP/1.1, HTTP/2 and HTTPS, graceful shutdown with a drain period, health checks, Prometheus metrics and request IDs.

Plays well with others

Use any tower layer (all of tower-http) as middleware, or run an Axeon app as a tower Service. No database lock-in.

Reads like the code you meant to write

Typed helpers parse input and answer bad input with the right status code. Middleware wraps what you choose. Everything is plain Rust, with no macros to learn.

  • Static paths beat parameters, and conflicts are caught at startup
  • Errors become JSON responses, and panics never leak internals
  • Test the whole pipeline in-process, with no ports
Routes
app.get("/users/:id", |req| async move {
    let id: u64 = req.param("id")?;          // 400 if not a number
    Ok::<_, ServerError>(Json(json!({ "id": id })))
});

app.post("/users", |req| async move {
    let user: NewUser = req.json()?;         // 415 / 400 / 422 for bad input
    Ok::<_, ServerError>((201, Json(user)))
});
See the full recipe

The Cookbook

24 complete, copy-pasteable recipes. Every program is compiled and tested against Axeon in CI, so what you copy works.

Getting started

Hello, World

A server in a handful of lines. Create a project, add Axeon, and answer your first request.

Open recipe
Getting started

Routing

Path parameters, wildcards, route groups, and how conflicts are settled.

Open recipe
Requests and responses

A JSON API

Parse JSON bodies, query strings and typed path parameters, and get the right 4xx status for free.

Open recipe
Getting started

A complete REST API

CRUD for one resource with shared state, validation, proper status codes and tests, in one file.

Open recipe
Requests and responses

Validation

Check incoming data and answer 422 with a per-field list of problems.

Open recipe
Requests and responses

Error handling

Return typed errors with ?, shape every error response yourself, and keep internals out of the response.

Open recipe
Requests and responses

Building responses

Status codes, headers, redirects, downloads and streaming, when a plain return value is not enough.

Open recipe
Middleware and state

Middleware

Closure middleware, middleware as a type, scoping to a router or one route, and passing data to handlers.

Open recipe
Middleware and state

Shared state

Register database pools, clients and counters once and read them from any handler.

Open recipe
Middleware and state

Hardening an API

Security headers, CORS, rate limiting, compression and request limits in one setup.

Open recipe
Auth and sessions

JWT authentication

Issue tokens at login and protect a router so handlers only run for valid bearer tokens.

Open recipe
Auth and sessions

API keys and basic auth

Check opaque tokens with your own async lookup, and protect internal tools with HTTP Basic.

Open recipe
Auth and sessions

Cookies, sessions and CSRF

A browser login flow with server-side sessions, signed cookies and CSRF protection.

Open recipe
Data and storage

Configuration from the environment

Load typed settings from environment variables and a .env file, with every problem reported at once.

Open recipe
Data and storage

A database with axeon-orm

Models, typed queries, migrations and pagination on SQLite or PostgreSQL, wired into Axeon errors.

Open recipe
Files and pages

Static files and single-page apps

Serve a directory with range requests and caching, and fall back to index.html for client-side routes.

Open recipe
Files and pages

HTML templates

Server-rendered pages with auto-escaping templates, layouts and form handling.

Open recipe
Files and pages

File uploads

Accept multipart uploads and stream them straight to disk, with a per-route size limit.

Open recipe
Realtime

Server-sent events

Push live updates to the browser over a plain HTTP response.

Open recipe
Realtime

WebSockets

Echo server and a broadcast chat room, using Tokio's broadcast channel.

Open recipe
Production

Production setup

Logging with request IDs, metrics, health checks, limits, timeouts and graceful shutdown.

Open recipe
Production

Testing your app

Call routes in-process, with no sockets and no ports, and assert on status, headers and body.

Open recipe
Production

Using tower middleware

Plug in any tower layer, including all of tower-http, and run Axeon as a tower Service.

Open recipe
Production

HTTPS and HTTP/2

Serve TLS directly with rustls and get HTTP/2 negotiated automatically.

Open recipe

Fast without the ceremony

Within spitting distance of the fastest Rust frameworks, and an order of magnitude ahead of Node.

FrameworkJSONPath paramp99 latencyMemory
actix-web 4207k req/s190k req/s5–9 ms10.6 MiB
axum 0.8195k req/s197k req/s2–3 ms8.5 MiB
Axeon176k req/s185k req/s2 ms8.9 MiB
Express 5 (8 workers)39k req/s45k req/s14–22 ms877 MiB

Apple M1, 128 keep-alive connections, best of three runs. Read the full methodology before drawing conclusions for your workload.

Ship your first endpoint in a minute.

1
Create a projectcargo new hello && cd hello
2
Add Axeoncargo add axeon
3
Paste a recipecargo run