Cameleeringsimoom

HTTP server engine for Rust

The HTTP server you build into your Rust program.

HTTP/1.1, HTTP/2 and HTTP/3, its own TLS 1.3, WebSocket and a client. Nothing underneath but the Rust standard library: no tokio, no hyper, no rustls, no OpenSSL. Write a function that answers a request and call start().

6.4x
faster start-up than the median of 20 servers; 1st of 21
20x
less memory per idle connection than the median of 18 servers; 2nd of 19
1.5x
lower CPU per request than the median of 18 servers; 1st of 19
src/main.rs
use simoom::{Outcome, Reply, Request,
             Server, StaticReply};
use std::sync::Arc;

fn main() {
    let hello = Arc::new(StaticReply::new(200,
        &[("content-type", "text/plain")],
        b"Hello, World!"));
    let server = Server::builder()
        .listen("127.0.0.1:8080")
        .service(move |_req: &mut Request<'_>,
                       reply: Reply<'_>| -> Outcome {
            reply.fixed(&hello)
        })
        .start()
        .unwrap();
    server.join(); // one event loop per CPU core
}
cargo add simoom · Rust 1.89+ · Linux, Windows, macOS

You wanted a door. Rust gave you a house.

Most programs that speak HTTP don't want a web server. They want a door: a place where requests come in and answers go out. A sensor reports its readings. A function wakes up, answers one call and goes back to sleep. A desktop app shows a dashboard in the browser. An integration engine takes webhooks all day.

In Rust, that door usually comes with a house attached: an async runtime, a few dozen crates, and a megabyte or more of code you didn't write and can't easily audit.

simoom is just the door.

You add one crate and write a plain function. Underneath, simoom runs one event loop per CPU core on epoll or io_uring (Linux), IOCP (Windows) or kqueue (macOS), and every protocol is a cargo feature, so you pay only for what you turn on.

  • HTTP/1.1keep-alive, pipelining, chunked bodies, strict parsing (RFC 9112)
  • HTTP/2over TLS and without it, with flood protection (RFC 9113)
  • HTTP/3over QUIC v1 on the same port number, announced with alt-svc
  • TLS 1.3its own: X25519, P-256, RSA, AES-GCM; client certificates (mTLS)
  • Live updatesWebSocket (also over HTTP/2 and HTTP/3) and server-sent events
  • Slow worka bounded offload pool that says 503 instead of queueing forever
  • A clientHTTP/1.1, HTTP/2, HTTP/3, pooling, proxies, WebSocket
  • Safetyunsafe in one crate only; every limit has a default

Why it exists: Cameleer needed a better door

Cameleer runs Apache Camel-style integration routes in Rust, with nothing outside the standard library. Its first HTTP server gave every connection its own thread: simple, but heavy. simoom was written from the ground up to replace it, under the same rule, and measured against it on the same machine.

Requests per second

293k–311kbefore: 172k–173k (1.7–1.8x)

p99 latency

0.32–0.44 msbefore: 0.87–0.91 ms

1,000 idle connections

2.7 MBbefore: 7.7 MB

Start-up with TLS

0.87 msbefore: 1.37 ms

Same machine (WSL2), server on 4 CPUs, 64 connections, closed loop, 2026-11-09; start-up 2026-11-11, 10 alternating rounds. One loss: idle memory with TLS is 3.3% higher (1,360 KB against 1,317 KB). Details in the benchmarks and the Cameleering ledger.

Against 20 servers, use case by use case

Campaign 4 measured simoom and the servers a team would otherwise pick (hyper, axum, actix-web, nginx, H2O, HAProxy, Envoy, Caddy, Go, Netty, Vert.x, Kestrel, uWebSockets and more) on the same droplets, in the same rounds. Each row is one use case and its main measure: simoom's place among the servers that ran it, and how far ahead or behind it is.

use case and measuresimoom's placeagainst the best otheragainst the median server
Health checks and status endpointsStatus endpoint, 256 clients: requests/s with 99% within 1 ms2nd of 19may-minihttp: 6% more than simoomsimoom 50% more
JSON APIsJSON API, 1 KB in and out, 256 clients: requests/s with 99% within 1 ms2nd of 12may-minihttp: 5% more than simoomsimoom 27% more
HTTPS APIs and new TLS clientsHTTPS API, 256 clients: requests/s with 99% within 1 ms1st of 8axum + rustls: simoom 30% moresimoom 2.1x more
Clients that connect for every requestA new connection per request, 192 clients: requests/s with 99% within 5 ms5th of 19xitca-web: 29% more than simoomsimoom 10% more
Service-to-service HTTP/2Service-to-service HTTP/2, 64 connections x 100 streams: requests/s with 99% within 5 ms2nd of 12H2O: 11% more than simoomsimoom 74% more
Mobile clients over HTTP/3HTTP/3, 64 clients: requests/s with 99% within 1 ms2nd of 4H2O: 43% more than simoomsimoom 65% more
Downloads64 KB downloads, 64 clients: requests/s with 99% within 5 msjoint 1st of 8actix-web: levellevel
Many idle connections10,000 idle connections: memory per connection2nd of 19nginx: 6% less than simoomsimoom 20x less
Traffic spikesTraffic spike at 195,000 requests/s offered: answers within 1 ms per second10th of 19actix-web: 22x more than simoom26% more than simoom
Slow attackersUnder 11,000 slow attackers: p99 of real requests6th of 19Go net/http: 44% lower than simoomsimoom 32% lower
Start-up, size and memoryStart-up, process start to first answer: simoom's default build (HTTP/1.1, HTTP/2, WebSocket)1st of 21hyper: simoom 57% fastersimoom 6.4x faster

Every ratio is against simoom on the same droplet in the same round, median of rounds. Charts for every measure and every server: the benchmarks.

Speed and cost, against every server that ran it

Requests per second while 99% of answers still arrive within 1 ms, with the load sent at a fixed rate from two other machines, and processor time per request at a fixed load. Each bar is indexed to simoom on the same droplet.

Status endpoint, 256 clients: requests/s with 99% within 1 ms

Bar: simoom = 100 on the same droplet, longer is better. Value: median of 3 rounds, higher is better; in brackets, simoom in the same runs.

may-minihttp154,590 req/s (simoom 145,171 req/s) · 6% more than simoom
simoom137,889 req/s
Vert.x (Java)100,036 req/s (simoom 102,713 req/s) · level
Netty (Java)96,967 req/s (simoom 102,713 req/s) · simoom 6% more
fasthttp (Go)95,444 req/s (simoom 102,713 req/s) · simoom 8% more
hyper110,931 req/s (simoom 137,889 req/s) · simoom 24% more
ntex108,326 req/s (simoom 137,890 req/s) · simoom 27% more
actix-web106,566 req/s (simoom 137,890 req/s) · simoom 29% more
axum101,477 req/s (simoom 137,890 req/s) · simoom 36% more
xitca-web92,021 req/s (simoom 137,890 req/s) · simoom 50% more
uWebSockets.js59,138 req/s (simoom 92,326 req/s) · simoom 56% more
HAProxy91,915 req/s (simoom 145,171 req/s) · simoom 58% more
nginx57,179 req/s (simoom 145,082 req/s) · simoom 2.5x more
Kestrel (.NET)36,871 req/s (simoom 102,713 req/s) · simoom 2.8x more
H2O40,551 req/s (simoom 145,082 req/s) · simoom 3.6x more
Go net/http24,600 req/s (simoom 92,326 req/s) · simoom 3.8x more
Envoy24,900 req/s (simoom 145,171 req/s) · simoom 5.8x more
Caddy12,546 req/s (simoom 145,082 req/s) · simoom 12x more
Cameleer's old server0 req/s (simoom 145,082 req/s) · only simoom met the target

HTTPS API, 256 clients: requests/s with 99% within 1 ms

Bar: simoom = 100 on the same droplet, longer is better. Value: median of 3 rounds, higher is better; in brackets, simoom in the same runs.

simoom134,004 req/s
axum + rustls103,343 req/s (simoom 134,004 req/s) · simoom 30% more
H2O79,386 req/s (simoom 103,311 req/s) · simoom 30% more
HAProxy61,431 req/s (simoom 103,311 req/s) · simoom 68% more
nginx40,777 req/s (simoom 103,311 req/s) · simoom 2.5x more
Go net/http28,755 req/s (simoom 167,300 req/s) · simoom 5.8x more
Caddy11,843 req/s (simoom 103,311 req/s) · simoom 8.7x more
Cameleer's old server0 req/s (simoom 103,311 req/s) · only simoom met the target

CPU per request at a fixed 50,000 requests/s

Bar: simoom = 100 on the same droplet, longer is better. Value: median of 3 rounds, lower is better; in brackets, simoom in the same runs.

simoom23.6 µs
may-minihttp28.6 µs (simoom 24.3 µs) · simoom 15% lower
Vert.x (Java)30.4 µs (simoom 24.5 µs) · simoom 19% lower
actix-web31.2 µs (simoom 24.1 µs) · simoom 23% lower
ntex32.1 µs (simoom 24.1 µs) · simoom 25% lower
xitca-web32.4 µs (simoom 24.1 µs) · simoom 26% lower
nginx32.9 µs (simoom 24.3 µs) · simoom 26% lower
hyper32.6 µs (simoom 24.1 µs) · simoom 26% lower
uWebSockets.js34.2 µs (simoom 24.5 µs) · simoom 28% lower
Netty (Java)34.6 µs (simoom 24.5 µs) · simoom 29% lower
Cameleer's old server36.2 µs (simoom 24.3 µs) · simoom 33% lower
HAProxy36.6 µs (simoom 24.3 µs) · simoom 34% lower
axum35.6 µs (simoom 23.6 µs) · simoom 34% lower
fasthttp (Go)33.2 µs (simoom 21.3 µs) · simoom 36% lower
H2O47.0 µs (simoom 24.3 µs) · simoom 48% lower
Go net/http53.0 µs (simoom 23.7 µs) · simoom 2.2x lower
Kestrel (.NET)64.1 µs (simoom 23.7 µs) · simoom 2.7x lower
Envoy68.4 µs (simoom 21.1 µs) · simoom 3.2x lower
Caddy86.3 µs (simoom 24.3 µs) · simoom 3.5x lower

JSON API, 1 KB in and out, 256 clients: requests/s with 99% within 1 ms

Bar: simoom = 100 on the same droplet, longer is better. Value: median of 3 rounds, higher is better; in brackets, simoom in the same runs.

may-minihttp124,126 req/s (simoom 118,427 req/s) · 5% more than simoom
simoom118,427 req/s
ntex83,326 req/s (simoom 95,678 req/s) · simoom 15% more
hyper71,171 req/s (simoom 84,755 req/s) · simoom 19% more
Netty (Java)109,736 req/s (simoom 135,188 req/s) · simoom 23% more
fasthttp (Go)86,456 req/s (simoom 109,366 req/s) · simoom 26% more
axum127,598 req/s (simoom 161,438 req/s) · simoom 27% more
Vert.x (Java)101,178 req/s (simoom 135,188 req/s) · simoom 34% more
actix-web54,349 req/s (simoom 84,755 req/s) · simoom 56% more
uWebSockets.js57,141 req/s (simoom 109,366 req/s) · simoom 91% more
Kestrel (.NET)22,515 req/s (simoom 109,366 req/s) · simoom 4.9x more
Go net/http20,755 req/s (simoom 109,366 req/s) · simoom 5.3x more

Where simoom is behind

  • Health checks and status endpoints: may-minihttp (6% more than simoom).
  • JSON APIs: may-minihttp (5% more than simoom).
  • Clients that connect for every request: xitca-web (29% more than simoom), Cameleer's old server (9% more than simoom), actix-web (5% more than simoom), may-minihttp (4% more than simoom).
  • Service-to-service HTTP/2: H2O (11% more than simoom).
  • Mobile clients over HTTP/3: H2O (43% more than simoom).
  • Many idle connections: nginx (6% less than simoom).
  • Traffic spikes: actix-web (22x more than simoom), nginx (4.7x more than simoom), xitca-web (3.2x more than simoom), uWebSockets.js (45% more than simoom) and 5 more.
  • Slow attackers: Go net/http (44% lower than simoom), HAProxy (34% lower than simoom), Vert.x (Java) (27% lower than simoom), Netty (Java) (20% lower than simoom) and 1 more.

When to use something else

simoom is new, small and focused. Pick the alternative when it fits better.

If you needUseWhy
A web server with a config file, static files or a reverse proxynginx, Caddy or h2osimoom is a library you build into a program, not a server you configure.
A large ecosystem of middleware and extractorsaxum or actix-websimoom has a router and optional helpers, not an ecosystem.
Years of production use inside the tokio worldhyperhyper is mature and battle-tested; simoom is at 0.1.0.
The simplest blocking server for a testtiny_httpIt is tiny and easy; simoom gives more protocols and throughput at more API surface.
A general QUIC transport, raw streams or 0-RTTquinn or s2n-quicsimoom's QUIC exists to carry HTTP/3 and refuses 0-RTT by design.
Independently audited TLSrustlssimoom's TLS is tested hard but not independently audited yet.

Quick start: three commands

Add the crate, paste the server above into src/main.rs, run it and send it a request. For HTTP/1.1 only, turn the default features off.

cargo add simoom
cargo run --release
curl http://127.0.0.1:8080/
# Cargo.toml: the smallest build, for a device or a function
simoom = { version = "0.1", default-features = false, features = ["http1"] }

Common questions

Is there a Rust HTTP server without tokio?

Yes. simoom has no async runtime. A service is a plain function that runs on the event loop thread; slow work goes to a bounded offload pool or to your own threads. Streaming, server-sent events and WebSocket all work without async.

Does simoom really have zero dependencies?

Yes. The workspace has no crates.io dependencies at all, not even for tests. TLS 1.3, QUIC, HTTP/2, HTTP/3, the compression codecs and the event loops are all in the repository. It is std-only, not no_std: it needs Linux, Windows or macOS.

How fast is it?

In campaign 4, simoom and 20 other servers ran on the same 4-vCPU DigitalOcean droplets. simoom was first for HTTPS throughput, CPU per request and start-up, joint first for downloads, and second for status endpoints and JSON APIs (behind may-minihttp), HTTP/2 and HTTP/3 (behind H2O) and idle memory (behind nginx). It is behind most servers under heavy overload and behind Go, HAProxy, H2O and the JVM servers under slow attackers. Every result is on the benchmarks page.

Is it a web server like nginx?

No. simoom is a library you build into a program. It has no configuration file, no static-file server and no reverse proxy. For those jobs use nginx, Caddy or h2o.

Is simoom ready for production?

It is at version 0.1.0 and the API can still change. It passes h2spec 146/146, 54 of 58 supported QUIC Interop Runner pairs and HTTP Garden with 0 desyncs, and Cameleer uses it as its HTTP engine. It has not had an independent security audit yet.

More answers in the FAQ.

A Cameleering project

A simoom is a hot, fast wind that crosses the desert. It travels with Cameleer, the integration engine, under the same practice: Cameleering, making software carry the same load on less and proving every gain against the original, on the same hardware, with the method published.

That is why every number on this site names its machine, its date and its baseline, and why the losses sit next to the wins.

Carry more on less. No claim without a number.