DEV Community

Cover image for NestJS vs Hono vs Fastify (2026): Benchmarked on Node.js 26
Waseem Anjum
Waseem Anjum

Posted on Originally published at fabwaseem.com

NestJS vs Hono vs Fastify (2026): Benchmarked on Node.js 26

Cross-posted from my blog. The original, with any updates, lives on fabwaseem.com.

"NestJS vs Hono vs Fastify" is one of the most common backend questions I see from TypeScript developers in 2026, and most answers are either opinion or benchmarks from 2023. So I ran my own: the same three routes on Express 5.3, Fastify 5.12, Hono 4.13, NestJS 12.3 on Express and NestJS 12.3 on Fastify, all on Node.js 26.13 (the current LTS), on the same machine, with the same load generator.

This post gives you the numbers, the exact code, and a straight answer on which one to pick for an API, a SaaS backend or an edge function.

The test setup

  • Machine: one 8-vCPU Intel Xeon Linux VM. The server was pinned to one CPU core with taskset -c 0 (Node runs your JavaScript on one thread, so this is a fair per-process number). The load generator, autocannon 8, ran on 6 other cores.
  • Runtime: Node.js v26.13.0.
  • Versions: express 5.3.0, fastify 5.12.8, hono 4.13.16 with @hono/node-server 2.1.6, @nestjs/core 12.3.3 with @nestjs/platform-express and @nestjs/platform-fastify 12.3.3. NestJS was compiled with TypeScript 5.9.3.
  • Load: 100 connections, no pipelining, 3-second warm-up, then 8 seconds per route.
  • Rounds: 3 full rounds, run one framework after another (interleaved), and I report the median of the 3.
  • Routes:
    • GET /json returns {"hello":"world"}
    • GET /users/:id returns the route parameter as JSON
    • POST /echo parses a small JSON body and sends it back

No logging, no validation, no database. This measures framework overhead only. Every request returned 2xx.

The code

Express 5:

import express from 'express';
const app = express();
app.use(express.json());
app.get('/json', (req, res) => res.json({ hello: 'world' }));
app.get('/users/:id', (req, res) => res.json({ id: req.params.id }));
app.post('/echo', (req, res) => res.json(req.body));
app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

Fastify 5:

import Fastify from 'fastify';
const app = Fastify({ logger: false });
app.get('/json', async () => ({ hello: 'world' }));
app.get('/users/:id', async (req) => ({ id: req.params.id }));
app.post('/echo', async (req) => req.body);
await app.listen({ port: 3000 });
Enter fullscreen mode Exit fullscreen mode

Hono 4 on Node.js:

import { Hono } from 'hono';
import { serve } from '@hono/node-server';
const app = new Hono();
app.get('/json', (c) => c.json({ hello: 'world' }));
app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }));
app.post('/echo', async (c) => c.json(await c.req.json()));
serve({ fetch: app.fetch, port: 3000 });
Enter fullscreen mode Exit fullscreen mode

NestJS 12 (one file, the adapter is picked by an env variable):

import 'reflect-metadata';
import { Body, Controller, Get, Module, Param, Post } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter } from '@nestjs/platform-fastify';

@Controller()
class AppController {
  @Get('json') json() { return { hello: 'world' }; }
  @Get('users/:id') user(@Param('id') id: string) { return { id }; }
  @Post('echo') echo(@Body() body: unknown) { return body; }
}

@Module({ controllers: [AppController] })
class AppModule {}

async function bootstrap() {
  const app = process.env.ADAPTER === 'fastify'
    ? await NestFactory.create(AppModule, new FastifyAdapter(), { logger: false })
    : await NestFactory.create(AppModule, { logger: false });
  await app.listen(3000);
}
bootstrap();
Enter fullscreen mode Exit fullscreen mode

Results: requests per second (one core, higher is better)

Framework GET /json GET /users/:id POST /echo
Fastify 5.12 85,448 82,040 59,746
Hono 4.13 (Node) 83,184 80,728 51,192
NestJS 12 + Fastify 70,082 69,010 48,596
Express 5.3 48,564 45,476 32,969
NestJS 12 + Express 43,844 39,340 29,563

Median of 3 rounds. Latency was low for all of them at this load: p50 was 1-3 ms and p99 was 2-11 ms. The highest p99 (11 ms) was NestJS on Express for POST /echo.

Results: startup time and memory

Framework Start to first 200 RSS idle RSS after load
Hono 4.13 90 ms 65.6 MB 110.5 MB
Express 5.3 115 ms 66.9 MB 115.7 MB
Fastify 5.12 158 ms 73.8 MB 116.5 MB
NestJS 12 + Fastify 404 ms 104.9 MB 136.2 MB
NestJS 12 + Express 486 ms 105.2 MB 149.9 MB

"Start" is the time from spawning the process to the first successful response, polled every 5 ms.

What the numbers say

1. Fastify and Hono are close; Express is roughly half as fast. On simple GET routes Fastify and Hono were within 3% of each other. Both did about 1.7-1.8x the requests of Express 5. Express 5 is a big cleanup (async errors, better path matching), but it did not change the performance picture.

2. Fastify wins on JSON bodies. On POST /echo, Fastify did 17% more requests than Hono (59,746 vs 51,192). Fastify has its own body parser and a compiled serializer path. Hono on Node goes through the Web Request adapter in @hono/node-server, and c.req.json() pays for that.

3. NestJS costs you about 16-19% on Fastify, and the adapter matters more than the framework. NestJS on Fastify kept 81-84% of raw Fastify's throughput on every route. NestJS on Express kept 87-90% of raw Express. But NestJS + Fastify was 60-75% faster than NestJS + Express on GET routes. If you already run NestJS, switching the adapter is the cheapest performance win you have.

4. NestJS starts 3-5x slower and uses ~40 MB more memory. That's the DI container, the module scan and reflect-metadata. It does not matter for a long-running API. It does matter for serverless cold starts and for scale-to-zero containers.

5. Hono starts fastest and uses the least memory. 90 ms and 65.6 MB idle. Add the fact that the same Hono app runs on Cloudflare Workers, Bun, Deno and Vercel, and it is the best default for small services and edge functions.

Caveats (read these before quoting the numbers)

  • This is framework overhead with trivial handlers. A real handler that hits Postgres for 2-5 ms will flatten these differences. At 30,000+ requests per second per core, the framework is rarely your bottleneck.
  • One VM, one core per server, 100 connections. Your hardware will give different absolute numbers; the ranking is what to take away.
  • Express used express.json(); Fastify and Nest used their default parsers. No schemas, so Fastify's schema-based serialization was not used. Fastify can serialize faster with a response schema; I did not test that here.
  • Hono was tested on Node.js through @hono/node-server. Hono on Bun or Workers is a different test.

Which one should you choose?

If you are building... Pick Why
A large team API with modules, DI, guards, OpenAPI NestJS on the Fastify adapter Structure and conventions; the Fastify adapter kept 81-84% of raw Fastify speed here
A high-throughput Node.js JSON API Fastify Fastest here, especially on POST bodies; mature plugin ecosystem
Edge functions, Workers, multi-runtime code, small services Hono Near-Fastify speed on Node, fastest startup, smallest memory, runs everywhere
An existing Express app Stay on Express 5 unless you have a measured performance problem Migration cost is real; the gap only matters at high load

My own default: Hono for small services and anything that might run on the edge, NestJS with Fastify when a SaaS backend needs structure and several developers. I covered the Express side in more depth in Hono vs Express, and what changed in NestJS itself in NestJS 12.

How to reproduce

Install the same versions, start each server pinned to one core, and run autocannon:

npm i hono@4.13.16 @hono/node-server@2.1.6 fastify@5.12.8 express@5.3.0 \
  @nestjs/core@12.3.3 @nestjs/common@12.3.3 @nestjs/platform-express@12.3.3 \
  @nestjs/platform-fastify@12.3.3 reflect-metadata rxjs autocannon@8

taskset -c 0 node fastify.mjs &
npx autocannon -c 100 -d 8 http://127.0.0.1:3000/json
npx autocannon -c 100 -d 8 -m POST -H content-type=application/json \
  -b '{"name":"Waseem","tags":["a","b","c"],"n":7}' http://127.0.0.1:3000/echo
Enter fullscreen mode Exit fullscreen mode

Run each framework a few times, alternate the order, and use the median.

FAQ

Is Hono faster than Fastify?

Not on Node.js in my test. On simple GET routes they were within 3% (Fastify 85,448 vs Hono 83,184 requests per second on one core). On a JSON POST body Fastify was 17% faster. Hono started faster (90 ms vs 158 ms) and used less memory.

Is NestJS slower than Express?

NestJS adds overhead on top of whatever adapter it uses. NestJS on Express did about 10% fewer requests than plain Express on GET /json. NestJS on the Fastify adapter was faster than plain Express by about 44% on the same route.

Should I use the Fastify adapter in NestJS?

If you don't depend on Express-only middleware, yes. In this benchmark NestJS on Fastify served 60-75% more GET requests per second than NestJS on Express, started faster (404 ms vs 486 ms) and used less memory under load.

Is Express 5 faster than Express 4?

I did not benchmark Express 4 in this test. Express 5 focuses on modern behaviour (promise-aware error handling, updated path matching) rather than speed, and in this test it was still about 43% behind Fastify on GET routes.

Which is best for a SaaS backend in 2026?

For a team project with auth, modules and many endpoints, NestJS on the Fastify adapter gives you structure without giving up much speed. For a small API or one that needs to run on Cloudflare Workers or Bun too, Hono is the simpler choice.


Originally published on fabwaseem.com.

Top comments (0)