tower-sessions
Async, pluggable session middleware for tower and axum web applications.
Repository Health
Technical Analysis
tower-sessions provides sessions as a tower middleware, giving Rust web services a key-value store tied to each visitor via a cookie-carried session ID. It ships an axum extractor so handlers can pull a Session directly out of a request, and it decouples storage entirely behind a SessionStore trait so teams can back sessions with whatever persistence layer fits their stack.
The design favors minimal overhead: session data is only loaded from its backing store when a handler actually touches it, so the middleware can sit anywhere in a route graph without a mandatory round-trip on every request. An ecosystem of community-maintained store crates (Redis, Postgres/SQLite/MySQL via SQLx, MongoDB, DynamoDB, Moka, and more) plugs into the same trait, and a CachingSessionStore wrapper lets any store be fronted by a faster cache.
What You Get
- A
SessionManagerLayertower middleware that manages the session cookie lifecycle (creation, save, and removal) transparently around request handling - An
axumSessionextractor that pulls the current session directly into handler function signatures - A
SessionStoretrait for implementing custom persistence backends, plus a built-inMemoryStorefor development and testing - Optional signed and private (encrypted) cookie modes via feature flags, layered on top of the
tower-cookiescrate - A
CachingSessionStorewrapper that fronts any backend store with a cache to reduce read-heavy round-trips - Configurable cookie attributes (name, path, domain,
SameSite,Secure,HttpOnly, expiry) via a builder API on the layer
Common Use Cases
- Adding server-side sessions to an
axumweb application without hand-rolling cookie and store plumbing - Building authentication flows on top of
axum-login, which is built directly on this crate - Persisting per-visitor state (shopping carts, wizard progress, feature-flag buckets) via a strongly-typed extractor pattern
- Layering a fast in-memory cache in front of a slower durable store (Postgres, MongoDB, Redis) for read-heavy session traffic
- Migrating between session backends without touching application code, since stores are swappable behind one trait
Under The Hood
Architecture
tower-sessions is split across a small Cargo workspace: tower-sessions-core defines the Session, Record, and SessionStore abstractions independent of any web framework; memory-store provides the default in-process backend; and the top-level tower-sessions crate wires these into a tower::Layer/Service pair (SessionManagerLayer/SessionManager in src/service.rs) that wraps tower_cookies::CookieManager. Cookie handling itself is abstracted behind a CookieController trait with PlaintextCookie, SignedCookie, and PrivateCookie implementations selected at the type level via with_signed/with_private, so the choice of cookie protection is encoded in the layer’s type rather than checked at runtime. The middleware’s call method loads a session lazily from the cookie’s session ID, inserts it as a request extension, invokes the inner service, and only then decides whether to save, extend, or remove the cookie based on whether the session was modified — keeping the store round-trip off the hot path for untouched sessions.
Tech Stack
The crate targets async Rust on Tokio, built directly against tower-service/tower-layer rather than the full tower crate, with http for request/response types and tower-cookies (itself built on the cookie crate) for cookie parsing and signing/encryption. async-trait powers the SessionStore trait’s async methods, time handles expiry and cookie Max-Age calculations, tracing provides structured instrumentation of the session lifecycle, and thiserror defines the store error type. The workspace pins exact internal versions (=0.15.0) across its member crates to keep tower-sessions-core, tower-sessions-memory-store, and the top-level crate in lockstep.
Code Quality
The crate enforces #![forbid(unsafe_code)] and #![deny(missing_docs)], and its CI runs cargo clippy --all-targets --all-features -- -D warnings, a cargo fmt --check pass, a cargo doc build that fails on broken intra-doc links, and a dedicated doc-test job that also generates coverage via cargo-tarpaulin uploaded to Codecov. Extensive integration-style tests in src/service.rs exercise cookie name/path/domain overrides, all three SameSite values, all three Expiry variants (including with always_save), signed and private cookie modes, and cookie removal semantics — each built around a real tower::ServiceBuilder stack rather than mocks. The public API is also documented almost entirely through runnable doc-tests, which double as usage examples and are compiled and checked in CI.
API Design
The library leans on Rust’s type system for ergonomics: enabling axum-core makes Session implement axum’s FromRequestParts automatically, so a handler needs only session: Session in its signature with no manual extraction step, and the same extractor pattern composes into custom strongly-typed wrappers. Feature flags (axum-core, memory-store, signed, private) keep the dependency footprint minimal for consumers who don’t need cookie signing or the bundled memory store. The builder-style SessionManagerLayer (with_name, with_expiry, with_secure, with_same_site, etc.) mirrors common tower middleware configuration idioms, and the SessionStore trait’s default method implementations (create, save, load, delete) mean a minimal custom store can be written in roughly a dozen lines, as shown directly in the crate’s own documentation.