Benchmarks
Compare the same work. A static C++ fastGet is not a Fastify route.
Logger middleware (logger()) must be off. stdout will dominate the numbers.
JavaScript handlers (application code)
Same-work harness on Apple Silicon (warmed multi-run avg): GET /json → { hello: "world" } from a lean JS callback (() => …, no middleware). Logger off.
| Server | GET /json (RPS) | Relative |
|---|---|---|
| Fastify v4.28 | ~68,000 | 100% |
Velociradix app.get | ~54,000 | ~80% of Fastify |
| Express v4.19 | ~11,500 | floor |
Beside Fastify on the same work. Handlers that read ctx.req (arity ≥ 1) still copy request fields into the bridge — expect a bit less than the lean number. Older docs listed ~20k, then ~42k before this pass.
C++ static path (fastGet) — different work
Same autocannon shape, but the route is app.fastGet("/json", { hello: "world" }): preformatted bytes, no JS callback, no per-request serialization.
| Server | RPS | Avg latency |
|---|---|---|
Velociradix fastGet | 114,490 | 8.26 ms |
Use this for /health, /ping, and other immutable payloads. Do not advertise it as “11× Express.” Express never had a chance to skip V8.
Older README tables that led with 181k req/s mixed this path (or a different harness) with framework handlers. That number is not the JS-handler result and is not used as a headline anymore.
Microbench vs node:http
npm run benchbench/bench-addon.mjs compares the addon to node:http on a fixed GET /plain response. That is useful for engine work. It is not a substitute for the Fastify/app.get table above.
How to read claims
| Claim | Treat as |
|---|---|
fastGet RPS | C++ static body |
app.get / ctx.json RPS | JS handler; compare to Fastify/Express |
| “Zero dependencies” | No npm runtime deps; native .node still exists |
Worker / SO_REUSEPORT | I/O and parse off the JS thread; JS still serializes your JSON |
Architecture: C++ engine.