From a technical standpoint, these are always impressive projects, but I've always wondered: has anyone ever encountered a use case where the Caddy was the bottleneck?
In my experience Caddy has worse latency and throughput than nginx. I've set up a service that frequently sends 600MB/s (~5gbps) with nginx and the CPU is just chilling at 50%, but Caddy on that machine bottlenecks at 300MB/s despite using 100% of the CPU. AES hardware acceleration was enabled and functional on both software. This is high throughput that most people won't see, but it was also on a far beefier machine than most people would use. Caddy would definitely be a bottleneck when serving media from a raspberry pi. My last attempt was in 2025, Caddy has probably improved since then.
That being said nginx has some terrible defaults so if you're just naively benchmarking it as a proxy out of the box, you might find Caddy to be better. For example nginx caches active request bodies (in and out) to temp files in many scenarios (to block the backend/upstream as little as possible), whereas Caddy is more of a transparent proxy.
I mean, nginx dang well should? This is just an incredibly synthetic http(s)/1.1 test for what its worth.
Like you totally could turn off garbage collection for caddy especially since this is only testing incredibly short single response queries that would never need GC. Shockingly you would actually get better performance than either nginx or zeroserve, but like the uselessness of this benchmark it'd mean nothing to the real world usage of these web servers.
I still think of eBPF as not being Turing-complete. There is still a complexity limit in the verifier. Even if someone did implement Game of Life by having the program set a timer to run itself. https://isovalent.com/blog/post/ebpf-yes-its-turing-complete...
The idea of jit compilation of a web server in a small project is pretty terrifying to me. The attack surface here is enormous.
And for what? My back end on a single host isn't pumping at 35k qps. If each request is 500 bytes, 35k qps is nearly 20mbps sustained with zero other io (in each direction). And this is using only two threads!
I think you'd be hard pressed to find an application where this is meaningfully useful versus just scaling horizontally. On a box that can run many threads in parallel, Caddy still vastly exceeds my ability to respond to pretty much any useful traffic. It's optimizing for a metric that wasn't a bottleneck in the first place.
I looked into writing an http server based on iouring myself, but all the resources I could find said iouring is less safe from a cybersecurity perspective.
Is there a safe way to use iouring for a webserver, or is libuv the better way to go, even though it has less performance?
Can someome enlighten me: What's the point of “running eBPF scripts in userspace”? Isn't being run in kernel space the whole point of eBPF in the first place?
I read this post and your post introducing zeroserve. One of the main parts of the original pitch was "no separate config file and scripts". Now you're adding a config file separate from the scripts. Is the pitch now that it's like Caddy but runs eBPF scripts in userspace?
Hi - zeroserve Caddy compat works by compiling Caddyfile to C. Technically I can keep the compiler in a separate binary/repository - but it just feels unnecessary.
zeroserve only understand eBPF at runtime. It's always the source-of-truth.
I was very taken by the other recent zeroserve headline that showed up, zeroserve: a zero-config web server you can script with eBPF:
> The twist is that you can drop eBPF programs into the tarball and they run on every request, in userspace, as sandboxed middleware - rewriting, authenticating, and rate-limiting requests, or reverse-proxying them to a backend when you want it to act as a gateway in front of your app.
It's such opposite audiences being targeted here. eBPF is for super nerds, Caddy for "i just want a just works http server". The headline here doesn't do much for me: I don't care about Caddy compatibility and 3x doesn't mean much to me (Caddy feels like it targets friendly and easy not performance). But eBPF scripting? Ok that's cool, that's rad.
23 comments
[ 2.6 ms ] story [ 47.5 ms ] threadThat being said nginx has some terrible defaults so if you're just naively benchmarking it as a proxy out of the box, you might find Caddy to be better. For example nginx caches active request bodies (in and out) to temp files in many scenarios (to block the backend/upstream as little as possible), whereas Caddy is more of a transparent proxy.
Like you totally could turn off garbage collection for caddy especially since this is only testing incredibly short single response queries that would never need GC. Shockingly you would actually get better performance than either nginx or zeroserve, but like the uselessness of this benchmark it'd mean nothing to the real world usage of these web servers.
https://github.com/losfair/zeroserve/blob/main/CADDY_COMPAT....
Very bizarre, never seen that before.
Thumbprints:
The usual 3400 lines lock file and AGENTS.md raise some questions about the aforementioned security, though.
People that trully need performance are not going to use a random server that has 0 support/ track record.
And for what? My back end on a single host isn't pumping at 35k qps. If each request is 500 bytes, 35k qps is nearly 20mbps sustained with zero other io (in each direction). And this is using only two threads!
I think you'd be hard pressed to find an application where this is meaningfully useful versus just scaling horizontally. On a box that can run many threads in parallel, Caddy still vastly exceeds my ability to respond to pretty much any useful traffic. It's optimizing for a metric that wasn't a bottleneck in the first place.
Is there a safe way to use iouring for a webserver, or is libuv the better way to go, even though it has less performance?
zeroserve only understand eBPF at runtime. It's always the source-of-truth.
> The twist is that you can drop eBPF programs into the tarball and they run on every request, in userspace, as sandboxed middleware - rewriting, authenticating, and rate-limiting requests, or reverse-proxying them to a backend when you want it to act as a gateway in front of your app.
https://su3.io/posts/introducing-zeroserve https://news.ycombinator.com/item?id=48425723 (272 points, 9d ago, 66 comments)
It's such opposite audiences being targeted here. eBPF is for super nerds, Caddy for "i just want a just works http server". The headline here doesn't do much for me: I don't care about Caddy compatibility and 3x doesn't mean much to me (Caddy feels like it targets friendly and easy not performance). But eBPF scripting? Ok that's cool, that's rad.