Tachyon-Web
⚠️ Pre-release software — read before depending on this
Tachyon-Web is pre-1.0, and pre-0.1 (
0.0.x) — it hasn't had a single "somehow stable" release yet. That means:
- Breaking changes can land in any release while we're still at
0.0.x.- Logical bugs are expected to exist. We cannot guarantee this crate is free of them — no team can honestly claim that about a project this size, least of all a young one. What we can guarantee: every line compiles under
#, and the code follows established best practices for input handling, resource limits, and request lifecycle management throughout. That makes the memory-safety class of bugs (buffer overflows, use-after-free, data races) essentially off the table, and meaningfully lowers — but does not eliminate — the risk of things like resource-exhaustion (DoS) bugs or accidental data exposure. Best practices reduce risk; they don't prove its absence, especially in a project this young.- This is not (yet) a mainstream, battle-tested crate. If you're building something where an outage or a security incident is unacceptable — payments, healthcare, anything regulated, anything with a real on-call rotation — use
axuminstead. It's maintained by a real team, it's been in production at scale for years, and that track record is worth more than anything on this page.Where Tachyon-Web does fit: side projects, internal tools, prototypes, and anyone enthusiastic about a framework that pairs Axum's API with more aggressive performance work and some genuinely nice quality-of-life defaults. If that's you — for a non-critical workload, or just to kick the tires — we'd genuinely love for you to try it and tell us what broke. A crate like this only gets to grow up into something people can rely on if people are willing to use it early and report back. We're not going to pretend we're something we're not, but we're also not going to pretend adoption doesn't matter.
A high-performance, multi-protocol web framework for Rust, built natively on
hyper and s2n-quic.
Tachyon-Web in one sentence: Axum's API and safety story, Actix's performance instincts, and Salvo's "batteries-included" approach to the stuff every real deployment eventually needs — HTTP/1.1, HTTP/2 (including cleartext h2c), HTTP/3, and fully automatic Let's Encrypt certificate management, all built in rather than assembled from five separate crates.
Why Tachyon-Web
- Axum's API, kept.
Router,.route(), and typed extractors (Path,Query,Json,State) work the way you already expect, and the Cargo feature flags are deliberately named and defaulted to match Axum's own (see Feature flags) — porting a handler over should feel like nothing changed. The one deliberate departure is middleware: Tachyon-Web uses its own native.hoop()middleware instead oftower::Layer, to avoid the overhead Tower's genericServiceabstraction introduces on the hot path. Tower middleware/services remain available as an opt-in bridge (thetowerfeature) for when reusing an existingtower-httplayer is worth more than that overhead. - Actix-tier performance, without giving up safety. Per-core
SO_REUSEPORTworker threads, allocation-free routing for the common case (arity-0 handlers, no path params), zero-copy static file serving with an in-memory cache, and lock-free hot paths — all with#![forbid(unsafe_code)]enforced crate-wide. We benchmark directly against Axum and Actix-Web (seebenches/) and treat any regression against either as a bug.- This is a live, working effort, not a settled claim — we still track a
concrete, measured gap against Actix (currently ~340k vs ~300k req/sec on
identical hardware for the same trivial handler, see
benches/optimistic). We'd rather be honest about an open gap than assert we're "fast" and leave it at that.
- This is a live, working effort, not a settled claim — we still track a
concrete, measured gap against Actix (currently ~340k vs ~300k req/sec on
identical hardware for the same trivial handler, see
- Salvo-style batteries included. Starting an HTTPS server is one call.
Automatic Let's Encrypt provisioning, renewal, and zero-downtime hot-swap
are built in — no external CLI tools, shell scripts, or cron jobs. HTTP/1.1,
HTTP/2 (cleartext or over TLS), and HTTP/3 (QUIC) are handled by the same
Routerand the same handlers; you choose which protocols to serve at theServercall site, not at the routing layer. - Native
.onionand.i2psupport, no sidecar processes. Publish the sameRouterdirectly as a Tor v3 hidden service (Server::serve_onion, built on pure-Rustarti-client/tor-hsservice— no externaltordaemon) or an I2P eepsite (Server::serve_i2p, built on an embeddedlibi2pd— no externali2pdprocess, no SAM/BOB bridge), including simultaneously alongside your regular clearnet listener. Seeexamples/onion_i2p_server.rsand thetor/i2pfeature flags below.
Quick start
use ;
use Html;
use TcpListener;
async
async
More complete examples (path/query/JSON extraction, middleware, shared state,
static file serving, sync handlers, serving over Tor/I2P) live in
examples/ and run with cargo run --example <name> (some,
like onion_i2p_server, need extra feature flags — see the example file).
HTTPS, in one call
For development, generate a throwaway self-signed certificate:
use ;
async
async
For production, serve_all_acme handles the entire Let's Encrypt lifecycle —
account registration, the HTTP-01 challenge flow, disk caching, and renewal
30 days before expiry — with no separate tooling:
use ;
async
async
WebSockets
use ;
use Response;
use Body;
use ;
async
async
let _app: = new.route;
Requires the ws feature.
Feature flags
Every flag below is real and load-bearing — it's either compiled into a default build right now, or it gates actual code and dependencies that disappear when it's off. If a flag is listed, flipping it does something.
Where a capability also exists in Axum, we kept Axum's own flag name and
default so porting a Cargo.toml over is a non-event:
| Flag | Default | Enables |
|---|---|---|
http1 |
✅ | Enables hyper's http1 support |
http2 |
✅ | Enables hyper's http2 support. Over plain TCP this is cleartext HTTP/2 ("h2c" — serve_http detects the connection preface, no ALPN/TLS needed); over TLS it's negotiated via ALPN. Note: Axum ships http2 off by default — Tachyon ships it on, since h2c-with-zero-config is a deliberate differentiator |
json |
✅ | Enables the Json extractor/response type (and the serde_json dependency) |
matched-path |
✅ | Enables capturing of every request's router path and the MatchedPath extractor |
original-uri |
✅ | Enables capturing of every request's original URI and the OriginalUri extractor |
form |
✅ | Enables the Form extractor |
query |
✅ | Enables the Query extractor |
cookies |
✅ | Enables request Cookie parsing and the Cookies extractor/IntoResponseParts jar (matching axum-extra's CookieJar), and the cookie dependency it needs |
tower-log |
✅ | Enables tower's own log feature — only has an effect together with the tower feature below |
ws |
WebSocket support (RFC 6455) |
Tachyon's own additions, beyond anything Axum has — matching how Axum treats
its own extras like ws, these default off too:
| Flag | Default | Enables |
|---|---|---|
tls |
TLS via rustls + aws-lc-rs |
|
cert-gen |
Self-signed certificate generation (tls::generate_self_signed_cert); requires tls |
|
http3 |
HTTP/3 over QUIC via s2n-quic; requires tls |
|
lets-encrypt |
Fully automatic Let's Encrypt certificate management; requires tls, cert-gen |
|
sse |
Server-Sent Events (response::sse::{Event, Sse, KeepAlive}) |
|
tower |
Bridge tower::Service/tower::Layer (e.g. existing tower-http layers) into the router — also implements tower::Service for CompiledRouter so app.oneshot(req) works |
|
fips |
Enforce FIPS-mode cryptography at startup; refuses to start otherwise | |
tor |
Native Tor v3 .onion hidden-service support (Server::serve_tor/serve_onion), via pure-Rust arti-client/tor-hsservice — no external tor daemon |
|
i2p |
Native I2P .b32.i2p eepsite support (Server::serve_i2p/serve_i2p_config), via an embedded libi2pd router — no external i2pd process. Note: unlike every other feature in this crate, i2p links C++ code through an FFI shim (tachyon-i2p/i2pd-sys), so it does not sit behind the crate's #![forbid(unsafe_code)] guarantee — see tachyon_web::server::i2p module docs before using it for anything security-sensitive |
At least one of http1/http2 must stay enabled (there's a friendly
compile_error! if you disable both — a server with no protocol support isn't
meaningful). Enable only what you need, e.g. HTTP/1.1 + HTTP/2 + TLS with
everything else off:
= { = "0.0.1", = false, = ["http1", "http2", "tls"] }
Or the smallest possible build — HTTP/1.1 cleartext only, no JSON/Form/Query/ MatchedPath/OriginalUri, no TLS, no crypto deps at all:
= { = "0.0.1", = false, = ["http1"] }
HTTP/2 over cleartext (h2c)
With the (default) http2 feature, Server::serve_http transparently speaks
HTTP/2 over plain, unencrypted TCP — no TLS, no ALPN. This is "h2c" / "HTTP/2
with prior knowledge": the server peeks at each connection's first bytes and
switches to an HTTP/2 stack if it sees the HTTP/2 client preface, falling back
to HTTP/1.1 otherwise. Browsers don't support it (they only ever negotiate
HTTP/2 via TLS ALPN), but plenty of non-browser clients do — curl --http2-prior-knowledge, gRPC clients, and internal service meshes where TLS
is terminated upstream (a load balancer, a sidecar) and re-encrypting hop-by-hop
would be redundant.
Minimum supported Rust version
Rust 1.92, edition 2024. Bumping the MSRV is not considered a breaking change while the crate is pre-1.0.
Acknowledgements
Tachyon-Web didn't arrive at its design in a vacuum — it's a deliberate synthesis of ideas we admired in three existing frameworks, and it wouldn't look the way it does without them:
- Axum is the project's main
inspiration and the reason the API looks the way it does.
Router, extractors,IntoResponse, the whole ergonomic shape of writing a handler — we didn't invent that, Axum did, and did it well enough that reimplementing it natively (rather than just depending on it) still felt worth doing. Any time this README says "matches Axum," it means we went and checked, not that we assumed. - Actix Web is where most of our
performance instincts come from. Per-core
SO_REUSEPORTworker threads, thread-local buffer reuse, and a healthy respect for what a per-request allocation actually costs at hundreds of thousands of requests per second — these are lessons the Actix team learned and published (in code, in benchmarks, in years of TechEmpower results) well before we came along to learn from them. - Salvo shaped our thinking on quality of life: that a web framework can just handle TLS, HTTP/3, and Let's Encrypt certificate management as first-class, built-in features, instead of making every user assemble that themselves from five different crates. That "batteries included, not bolted on" instinct is directly downstream of seeing Salvo do it first.
Thank you to the maintainers and contributors of all three projects — for the code, the design decisions, and the prior art. We're grateful, and we mean it.
License
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.