印 benchmarks
Fast, and still every request checked.
Every inkan request below was validated against its contract, typed, given an id and trimmed to its response schema before it went out. These are the numbers with all of that switched on.
134.4
inkan on uWebSockets.js
2.9× Express, past bare node:http
91.0
inkan on node:http
2.0× Express, with every check on
100
node:http, by hand
the line everyone is measured against
Every scenario
Pick one and the servers sort themselves. 7 of the twelve scenarios here, from a fixed answer to a body of 50 objects checked one by one.
the geometric mean over all twelve scenarios of the run · node:http = 100 · higher is better
- 1inkan on uWebSockets.js@inkanjs/uws, measured with 0.6.0134.4134.4
- 2node:http, by handthe baseline100.0100.0
- 3inkan, sealedinkan seal93.293.2
- 4inkanon node:http91.091.0
- 5Fastifyschemas, like inkan89.989.9
- 6Honochecks by hand84.584.5
- 7Expresschecks by hand46.046.0
| server | score | hello | params + query | body of 50 | answer of 100 | 400 routes | 404 | 400 |
|---|---|---|---|---|---|---|---|---|
| inkan on uWebSockets.js | 134.4 | 147% | 148% | 104% | 99% | 149% | 154% | 115% |
| node:http, by hand | 100.0 | 100% | 100% | 100% | 100% | 100% | 100% | 100% |
| inkan, sealed | 93.2 | 96% | 95% | 99% | 90% | 92% | 97% | 76% |
| inkan | 91.0 | 96% | 91% | 89% | 88% | 89% | 93% | 72% |
| Fastify | 89.9 | 95% | 97% | 92% | 78% | 91% | 94% | 63% |
| Hono | 84.5 | 92% | 78% | 89% | 97% | 75% | 78% | 82% |
| Express | 46.0 | 49% | 47% | 62% | 70% | 21% | 21% | 49% |
How it is measured
印 The same work
inkan and Fastify check with schemas, the others by hand. Nobody wins by skipping the check.
印 Right answers first
Before a server is measured on a scenario, its answer is checked. A wrong or empty answer is not fast, it is wrong.
印 All at once, taking turns
Every server runs for the whole bench, and each scenario is measured for all of them back to back. A slow moment of the machine hits everyone alike.
印 Against node:http
Every number is requests per second next to a bare node:http server doing the same, as 100. The machine drops out of it.
印 No single scenario wins
The score is the geometric mean over all twelve scenarios, so one great number cannot carry a server, nor one bad one sink it.
印 The median of rounds
3 rounds, 15 seconds each after a warm-up, the median of them. On a GitHub Actions runner, 4 cores, with autocannon.
A range, not a rank
A run on another day moves each server by a few points. On node:http inkan is level with Fastify or a little ahead: in front in two of the three runs of the 0.8.0 bench, level in the third, and not in every scenario. inkan also does a bit more per request than the others: an id for every request, and every key an answer's contract does not list kept back.
Your routes are not these routes. Measure the ones you have: the bench is a folder in the repository, and the same workflow runs it on GitHub for anyone.
The apps for Fastify, Hono and Express are written by us, and a benchmark is only as fair as those are. If you know a faster way to write one of them that does the same work, send a pull request: the numbers here will change with it.
this run: 2026-10-20 · Node 24 · GitHub Actions runner, 4 cores · the workflow
git clone https://github.com/inkanjs/inkan
cd inkan/bench && npm install
# req/s, latency and memory, every server at once
node run.mjs node,fastify,hono,inkan,express 10 3
# what one request costs the server, in CPU time
node cpu.mjs node,fastify,hono,inkan