simoom / Use cases / Serverless
Serverless and scale to zero
An HTTP layer that isn't your cold start
A function that scales to zero pays for its start-up on every cold request, and pays for its memory every second it runs. In benchmark campaign 4 (2026-11-12), simoom's default build gave its first answer 0.94 ms after the process started, the fastest of 21 servers, and sat at 901 KB of memory at rest, so the time and the memory go to your code.
Start-up, measured
Cold start is the time from spawning the process to the first successful answer on its port. In campaign 4 every server ran on the same DigitalOcean c-4 droplet as simoom, in the same round.
| server | start-up to first answer | memory at rest (PSS) | program size, stripped |
|---|---|---|---|
| simoom, default build (HTTP/1.1, HTTP/2, WebSocket) | 0.94 ms | 901 KB | 735 KB |
| simoom, full server (also TLS 1.3 and HTTP/3) | 1.49 ms | 1,844 KB | 1,550 KB |
| hyper | 1.48 ms | 1,374 KB | 2,069 KB |
| axum | 1.56 ms | 1,518 KB | 2,246 KB |
| actix-web | 1.81 ms | 1,885 KB | 2,450 KB |
| Go net/http | 3.74 ms | 8,088 KB | 6,180 KB |
| may-minihttp | 8.03 ms | 9,061 KB | 515 KB |
| nginx | 19.57 ms | 72,469 KB | 1,283 KB |
| Kestrel (.NET) | 366.56 ms | 70,559 KB | not a single executable |
| Netty (Java) | 467.01 ms | 74,067 KB | not a single executable |
Campaign 4, 2026-11-12, a selection of the 21 servers; the median of the 20 others started 6.4x slower than simoom's default build. Program size is shown only for self-contained executables. With HTTP/3 on, simoom starts every event loop at once instead of one, part of why the full server starts later than the default build. The platform's own sandbox start comes on top for every runtime. All servers: start-up, memory at rest. On a workstation, against the server it replaced, see Cameleer's old server.
Why it starts fast
Less to set up
- No async runtime to build before the first request.
- Lazy loops: start returns with one loop running; the others start in the background once that loop gets busy.
- The descriptor table is grown once at start, not while threads run.
- A P-256 key's signing table is built on the first signature, not at load.
Less to carry
- An HTTP/1.1-only build adds 215 KB; the full server with HTTP/3 adds 935 KB.
- Nothing from crates.io, so nothing extra to download, compile or ship.
- One event loop per CPU core, so a small function with one vCPU runs one loop.
The start-up work behind these numbers is described in runtime. Build options: features and size.
A function's HTTP server
Container platforms such as Cloud Run send requests to a port; listen on it and answer. A graceful stop tells clients to finish when the platform retires the instance.
use simoom::{Backend, Reply, Request, Server};
use std::time::Duration;
let server = Server::builder()
.listen("0.0.0.0:8080")
.threads(2) // 0 = one loop per core (the default)
.backend(Backend::IoUring) // Linux 6.1+, falls back to epoll
.service(|_: &mut Request<'_>, r: Reply<'_>| r.body_static(b"ok"))
.start()
.unwrap();
// ...
server.stop(Duration::from_secs(5)); // tells clients to finish, then waits up to 5 s
server.join();
simoom serves HTTP on a socket. On AWS Lambda that means a container image or an HTTP adapter in front of the port: simoom does not speak the Lambda Runtime API itself. Cameleer, which uses simoom, is its own Lambda runtime: see Cameleer on AWS Lambda.
Common questions
What is the smallest Rust web server for AWS Lambda or other serverless platforms?
An HTTP/1.1-only simoom build adds about 215 KB to a binary. In benchmark campaign 4 (2026-11-12), simoom's default build (HTTP/1.1, HTTP/2, WebSocket) gave its first answer 0.94 ms after the process started, the fastest of 21 servers (hyper: 1.48 ms), and used 901 KB of memory at rest. For the smallest build, turn off the default features and keep http1.
Does simoom speak the AWS Lambda Runtime API?
No. simoom serves HTTP on a socket, which suits container platforms such as Cloud Run directly. On Lambda it runs behind an adapter or in a container image. Cameleer, which uses simoom as its HTTP engine, is its own Lambda runtime.
How fast is the cold start with TLS?
In benchmark campaign 4 (2026-11-12), simoom's full server, with TLS 1.3 and HTTP/3 built in, gave its first answer 1.49 ms after the process started: level with hyper (1.48 ms) on the same droplet, and ahead of axum with rustls (1.91 ms). With HTTP/3 on, simoom starts every event loop at once; the default build starts one loop and adds the others when it gets busy.
Do I need tokio for a serverless HTTP handler in Rust?
No. simoom has no async runtime. A service is a plain function; slow work goes to a bounded offload pool or to your own threads.
How much memory does an idle simoom server use?
In benchmark campaign 4 (2026-11-12), the default build's process used 901 KB of PSS at rest, and the full server with TLS 1.3 and HTTP/3 used 1,844 KB. On the same droplets hyper used 1,374 KB and axum 1,518 KB, less than simoom's full server, and nginx 72,469 KB.
Measure it yourself
Build the hello example in release mode and time the first answer on your platform.
cargo add simoom cargo run --release -p simoom --example hello -- 127.0.0.1:8080 # from a checkout of the repository