# fastify/benchmarks measures framework overhead, and its own documentation warns you not to read it as a real world result

> The fastify benchmarks repository runs a fixed autocannon workload against more than twenty Node.js frameworks, publishes the table in its README, and keeps cold start numbers in METRICS.md. The harness is well structured and the caveats are stated up front, but the results come from shared virtual hardware and measure routing overhead rather than application work.

**fastify/benchmarks** — Fast and low overhead web framework fastify benchmarks

- Repository: https://github.com/fastify/benchmarks
- Website: https://github.com/fastify/fastify
- Stars: 634 · Forks: 253
- Language: JavaScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/fastify-benchmarks

## A harness for framework overhead, not a benchmark of your app

The fastify/benchmarks repository exists to answer one question: how much overhead does each Node.js web framework add to a request. The project states it directly, saying the benchmarks do not pretend to represent a real world scenario but give a good indication of the framework overhead.

That framing is the correct one, and it is stated in the first screen of the document rather than buried. It also tells you what the harness deliberately excludes: your database driver, your template engine, your authentication middleware, the shape of your payload, and everything your handlers do.

The project belongs to the fastify organisation and its homepage points at the fastify framework repository, so there is an obvious incentive in the setup. The way to read the results honestly is to treat the table as a comparison of routing layers on one machine at one moment, and to note where a framework sits relative to the raw Node http server, which is the floor that any framework adds to.

The repository also serves a second, less obvious purpose. Because every framework in the table is wired up through the same small server files under benchmarks/, that directory doubles as a set of working examples of how to mount the same route in each framework, which is often more useful than the numbers themselves.

## The commands are two: bench and compare

Usage is deliberately small. You clone the repository and then:

```
node ./benchmark [arguments (optional)]
```

There are two arguments. The first is bench, which benchmarks one or more modules, and the second is compare, which produces comparative data for the benchmark results.

The order matters, and the documentation is explicit about it with a note to create the benchmark before comparing. The comparison step reads the stored results of the run, so comparing without benchmarking first gives you nothing useful.

Two options extend the comparison. The -t flag compares all test results at once in a single table. The -p flag extends the comparison table with percentage values based on the fastest result, which is the form most people want when they ask why their framework is slower.

Two scenarios are defined. The get scenario is the default and serves a GET request on the root path responding with a JSON object with a hello property set to world, with the server implementations living in the benchmarks/ directory. The post scenario handles a POST on the same path with a JSON body that is parsed and echoed back, with its servers in benchmarks/post/.

To run non interactively you pass the scenario as the fifth argument, and when comparing you select it with -s:

```
node ./benchmark bench y 100 10 40 post
node ./benchmark compare -t -s post
```

Those numbers are the autocannon parameters: 100 connections, 10 pipelined requests, over 40 seconds.

## Only frameworks that pass a usage bar get into the list

A benchmark list is only as meaningful as the criteria for joining it, and this project states its own.

The project sets out the minimal requirements a framework must meet to be included, and it begins with a criterion about interest rather than technical merit. The framework should captivate users interest, and to be included in the list it must ensure active usage, defined as a minimum of 500 downloads per week. The second requirement is that the repository must be maintained and show at least one event, meaning a comment, an issue or a pull request, in the last month.

The third requirement is technical: the framework must use the Node.js HTTP module. That last condition is the one that keeps the comparison honest. A framework that sits on top of its own server stack, with its own listener and its own protocol handling, is not competing with the same primitive, and its overhead number would not be comparable.

The practical consequence for a reader is that the table is a sample of frameworks serious enough to have weekly users and an active repository, filtered to those built on the same underlying server. It is not a ranking of every Node framework that exists, and the absence of a project from the list says nothing about that project's quality.

It also means the list changes over time. A framework that stops meeting the activity requirement drops out, and a new one appears when it starts meeting it.

## Reading the published table with its caveats attached

The project publishes the results of the run that produced the current table, and it includes the machine and method so the numbers can be judged.

The run was on linux x64 with 4 vCPUs and 15.6GB of memory, using Node v24.22.0, and it is timestamped. The method is an autocannon invocation with 100 connections, 40 seconds of duration and 10 requests pipelined against a local server on port 3000, run for two rounds with one as a warm up and one as the measurement.

The table has columns for version, whether the framework ships a router, requests per second, latency in milliseconds and throughput. Fastify 5.12.7 appears with a router, at 91,539.2 requests per second and 10.40 milliseconds of latency. Above it sit restana and 0http, and below it are connect, polka and the raw node-http server at 89,334.4 requests per second.

The caveat that matters most is stated at the top: the benchmarks run automatically on GitHub Actions, which means they run on virtual hardware that can suffer from the noisy neighbour effect, so the results can vary. A table of twenty frameworks differing by a few thousand requests per second on a shared virtual machine is not a reliable ordering, and the gap between the top entries is well inside that noise.

What the table does show reliably is the shape of the distribution. Frameworks built directly on the Node HTTP server cluster near the top, and the ones with heavier middleware stacks sit lower. Express 5.3.0 appears at 68,965.6 requests per second, and the express-with-middlewares row shows the cost of adding middleware to the same framework.

## Cold start numbers live in a separate file

Throughput is only one of the two questions the project tries to answer, and the second one is handled elsewhere.

The summary section points readers to METRICS.md for cold start metrics, and the repository has a metrics/ directory alongside a lib/ directory and the benchmark scripts. Cold start matters for serverless deployments and for any environment where a process is started on demand, where the framework's bootstrap cost can dominate the first request.

The npm scripts show how that side is driven. The metrics run script starts a startup measurement entry point in metrics/startup.cjs, and the metrics summary script processes the results with the update flag in metrics/process-results.cjs. There is also a separate results file for the POST scenario, benchmark-results-post.json, alongside benchmark-results.json for the GET scenario, so the two scenarios keep their data apart.

The repository therefore gives you two views of the same frameworks: steady state throughput in the README table, and startup behaviour through the metrics tooling. If your deployment shape makes one of those the deciding factor, the other one may be the number you should have been comparing all along.

## MIT terms, no releases, and a repository that runs itself

The licence is MIT, and the package metadata is a plain Node package with no dependencies on the frameworks being measured in the main section, because each benchmark server brings its own.

The scripts section of package.json is short and tells you how the project is meant to be used:

```json
    "start": "node benchmark.js",
    "compare": "node benchmark.js compare --",
    "test": "standard | snazzy",
    "metrics:run": "node metrics/startup.cjs",
    "metrics:summary": "node metrics/process-results.cjs -u"
```

The start and compare scripts mirror the command line usage described in the documentation, the test script runs standard through snazzy for linting, and the two metrics scripts cover the cold start measurement and its summary. The standard configuration excludes lib/packages.js from linting, which is the file that presumably carries the dependency list of every framework under test.

The dependency list in the same file is the roster of frameworks under comparison, and it includes the packages for AdonisJS, Elysia, Hapi, Hono, Koa and its router, TinyHTTP, tRPC, the whatwg-node server, 0http, connect, Express and Fastify itself. The measurement tooling is autocannon, with autocannon-compare for the comparison table, plus chalk and cli-table for the output and commander for argument parsing.

There are no GitHub releases, so there is no version to pin and nothing to upgrade. The repository is not archived and the last push was on 2026-10-19, the same day as the run recorded in the README table, which tells you the table is refreshed as part of the normal commit cycle rather than curated separately.

## Conclusion

Use fastify/benchmarks when you want a reproducible way to compare routing overhead across Node web frameworks on identical hardware, and when you are willing to read the caveats before drawing conclusions. Do not use its published table as an application performance claim, because the harness measures framework overhead on shared virtual machines and excludes the database, the template engine and the serialisation your real service does. Before adopting it, run node ./benchmark bench and node ./benchmark compare -t on hardware close to your production machines, and read METRICS.md if cold start is what actually matters to you.

## FAQ

### What does the fastify/benchmarks repository do?

It runs a fixed autocannon workload against more than twenty Node.js web frameworks and publishes the results, so that framework routing overhead can be compared on identical hardware. The project states the numbers give a good indication of framework overhead rather than representing a real world scenario.

### How do I run the fastify benchmarks?

Clone the repository and run node ./benchmark. The first argument is bench to benchmark modules, and the second is compare to produce comparative data. You can compare all results in one table with compare -t, and add percentages based on the fastest result with compare -p.

### What are the get and post benchmark scenarios?

The get scenario is the default and serves a GET request on the root path returning a hello world JSON object. The post scenario handles a POST on the same path with a JSON body that is parsed and echoed back. The servers for each live in benchmarks/ and benchmarks/post/.

### Why do the fastify benchmark results vary between runs?

The benchmarks run automatically on GitHub Actions, so they run on virtual hardware that can suffer from the noisy neighbour effect. The project states directly that this means the results can vary.

### Which frameworks are allowed in the fastify benchmark list?

A framework must ensure active usage with a minimum of 500 downloads per week, must have an active repository with at least one event in the last month, and must use the Node.js HTTP module.

### Where are cold start numbers for these frameworks?

Cold start metrics are kept separately from the throughput table and are pointed to by the README, with the measurement scripts in the metrics/ directory driven by the metrics:run and metrics:summary npm scripts.

## Sources

- [fastify/benchmarks on GitHub](https://github.com/fastify/benchmarks)
- [Issues](https://github.com/fastify/benchmarks/issues)
- [License: MIT](https://github.com/fastify/benchmarks/blob/main/LICENSE)
- [Project website](https://github.com/fastify/fastify)
- [README](https://github.com/fastify/benchmarks/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fastify-benchmarks
