rws vs nginx vs Caddy
How rws compares with nginx and Caddy as a web server and reverse proxy — certificates, config, HTTP/3, load balancing, auth, observability, Kubernetes and speed — with sources and measured benchmarks.
Short answer: pick rws if you want one binary that serves files, gets its own certificates, load balances and adds auth from one TOML file, with the same engine available as a Rust library. Pick Caddy for the same "HTTPS by default" experience with a large Go plugin ecosystem. Pick nginx when you need the most battle-tested server, the lowest memory use, or modules only nginx has.
Facts about nginx and Caddy were checked against their documentation on 2026-11-06 (sources). Tell us on GitHub if something has changed.
At a glance
| rws | Caddy | nginx | |
|---|---|---|---|
| Automatic HTTPS | Built in: HTTP-01, TLS-ALPN-01, DNS-01 (RFC 2136, Cloudflare, Route 53, exec), wildcards, on-demand TLS | Built in and on by default: HTTP-01, TLS-ALPN-01, DNS-01 via plugins, on-demand TLS, a local CA for localhost | Official nginx-acme dynamic module (HTTP-01, TLS-ALPN-01; no DNS-01), or certbot |
| Config | One rws.config.toml; rws --check; hot reload on SIGHUP or file change; admin API |
Caddyfile or JSON; caddy validate; admin API |
nginx.conf; nginx -t; reload; Control API since 1.31.5 (off by default) |
| HTTP/3 (QUIC) | On by default with TLS | On by default | Yes, since 1.25.0 (marked experimental) |
| Load balancing | Round robin, random, least connections, IP hash, weights, sticky cookies, circuit breaker, retries, active health checks | Random, round robin, weighted, least connections, IP/URI/header/cookie hash, active and passive health checks, retries | Round robin, least connections, least time, hash, random, sticky (1.29.6+); active health checks in NGINX Plus |
| Auth | Bearer, JWT, basic, forward auth, OIDC sign-in; fails closed when misconfigured. SAML in the library | Basic, forward auth; more via plugins | Basic, auth_request; JWT and OIDC in NGINX Plus |
| Observability | Prometheus metrics with native histograms, OpenTelemetry traces, metrics and logs, JSON access log, admin UI with traffic analytics (people, AI agents, bots) | Prometheus metrics (HTTP metrics opt-in), OTLP metrics, OpenTelemetry tracing, structured JSON logs | stub_status, OpenTelemetry tracing module; full metrics API in NGINX Plus |
| Kubernetes | Gateway API controller (v1.6.3 conformance, all five Gateway profiles), Helm chart | Ingress controller (caddyserver/ingress, work in progress); no Gateway API implementation | NGINX Gateway Fabric (Gateway API), NGINX Ingress Controller |
| Extending | A Rust crate: routes, middleware, MCP server, ORM; WASM plugins | Go plugins compiled in (xcaddy) | C modules, njs, Lua via OpenResty |
| License | MIT | Apache-2.0 | BSD-2-Clause |
Speed
Measured on one 4-CPU GitHub Actions runner, 64 keep-alive connections, no compression, access logs off. The method and every number are on the benchmarks page. In short: rws and nginx lead on requests per second and CPU per request in most scenarios; nginx uses the least memory in every scenario.
When to choose which
- rws: a small team's whole front door in one file (static site, automatic certificates, a few proxied apps, auth and rate limits), or a Rust app that wants a production HTTP server inside it.
- Caddy: you want automatic HTTPS and already rely on a Caddy plugin.
- nginx: very high traffic on minimal memory, an existing nginx setup, or a module only nginx has.
Moving from nginx or Caddy
- Quick start: static files and a proxy in five minutes
- Automatic HTTPS
- Config-driven proxy
Sources
- Caddy: automatic HTTPS, global options, reverse_proxy, directives, metrics, ingress, license
- nginx: ACME module, HTTP/3, upstream, changes, JWT (commercial), OpenTelemetry, Control API (1.31.5), license
- Kubernetes: Gateway API implementations