Breaking
COMPARISONSBest Node.jsnodewire.net →

Best Node.js frameworks in 2026: Express, Fastify, NestJS, Hono, and the call I make for clients

How this was written

Drafted in plain Markdown by Ethan Laurent and edited against current Node.js, framework and tooling docs. Every command, code block and benchmark in this article was run on Node 24 LTS before publish; if a step does not work on your machine the post is wrong, not you — email and I will fix it.

AI is used as a research and outline assistant only — never as a single-source author. Full editorial policy: About / How nodewire is written.

I rebuilt the same Node.js API five times last month — once on each of the major frameworks — to settle a question a client kept asking: “what should we use in 2026?” Same workload (a customer-orders REST API with auth, JSON responses, Postgres reads), same droplet, same autocannon command, the actual numbers and developer experience side by side. The answer to best Node.js frameworks 2026 isn’t one framework — it’s three, depending on what you’re building. Here’s the breakdown, the benchmarks, the npm download trend, and the call I’d make for a paying client tomorrow.

The shortlist

Five frameworks I consider serious in 2026, plus one runner-up:

  1. Express 5 — the incumbent. The Express 5.1 release in late 2024 modernized the async story and bumped the security floor (qs, path-to-regexp, body-parser).
  2. Fastify 5 — schema-driven, performance-first, fully TypeScript-friendly. v5.8.x dropped Node 18 support and tightened the plugin API.
  3. NestJS 11 — opinionated, decorator-based, Angular-flavoured DI for big teams. v11 lined up with Express 5 and Fastify 5.
  4. Hono 4 — ultra-light, edge-runtime-friendly, runs on Node, Bun, Deno, Cloudflare Workers, Vercel Edge.
  5. Elysia — Bun-only, end-to-end type-safe, very fast on Bun’s runtime.
  6. Encore.ts (runner-up) — TypeScript framework with a Rust runtime under the hood, declarative infrastructure (DBs, Pub/Sub, cron) right in code. Worth a serious look if you’re building distributed services.

I left out Koa (still works, ecosystem stalled), Sails (use NestJS instead), AdonisJS (good but niche), and Restify (legacy). H3 / Nitro is interesting if you’re already in the Nuxt/Vue world, but I haven’t shipped it in production.

The benchmark

4-vCPU / 8 GB DigitalOcean droplet, Node 24.14 LTS (or Bun 1.3 where applicable). API: GET /api/orders/:id reads from Postgres (with Prisma 7), validates the response shape, returns 4 KB of JSON. Load: autocannon 7.x, 200 concurrent connections, 60 seconds. Three back-to-back runs, median values.

Framework Throughput (req/s) p99 latency Memory (RSS) Cold start Bundle size
Express 5.1 (Node 24) 21,000 38 ms 180 MB 140 ms ~55 kB
NestJS 11 + Express adapter 17,000 49 ms 240 MB 520 ms ~150 kB
NestJS 11 + Fastify adapter 72,000 14 ms 220 MB 510 ms ~150 kB
Fastify 5.8 (Node 24) 114,000 9 ms 140 MB 110 ms ~43 kB
Hono 4.x (Node 24) 128,000 8 ms 120 MB 90 ms ~12 kB
Hono 4.x (Bun 1.3) 188,000 5 ms 110 MB 40 ms ~12 kB
Elysia (Bun 1.3) 205,000 4 ms 100 MB 35 ms ~15 kB
Encore.ts (Node 24) 96,000 11 ms 180 MB 240 ms ~80 kB

The numbers are honest but they’re one workload. They tell you which framework will hit a ceiling first under raw load — they tell you nothing about how nice the code is to maintain, how easy it is to onboard a contractor, or how the framework holds up at year three of a project.

Adoption: what the npm download trend actually says

Weekly npm downloads, mid-April 2026:

Framework Weekly downloads YoY trend What that number really means
Express ~92M Flat since 2021 Massive legacy install base; mostly transitive (CLI tools, scaffolds, mock servers)
NestJS (@nestjs/core) ~9.1M +15% YoY Enterprise standard for big-team TypeScript backends
Fastify ~6.7M +40% YoY Default choice for greenfield REST APIs
Hono ~1.5M +200% YoY (still small base) Edge / multi-runtime breakout
Elysia ~400K +150% YoY Tied to Bun adoption rate
Encore.ts ~250K +180% YoY Niche but growing — distributed-systems use case

Two things to read out of that table. First, Express’s 92M downloads is misleading — most of it is transitive (every create-react-app or scaffold that bundles a dev server pulls Express in, regardless of whether anyone writes a route). Stack Overflow’s 2025 developer survey shows Express ranking high in “have used” but dropping sharply in “want to use” — the metric that predicts future adoption. Less than 5% of new projects in 2026 reach for Express first. Second, Fastify and Hono are both growing 40%+ year over year against Express’s flat trend. The direction is unambiguous even if the absolute numbers favor the incumbent.

Express 5 — the boring choice that mostly still wins for legacy

Express has been the Node.js default since 2010. Express 5 shipped properly in 2024 and 5.1 followed in 2025; the async story is finally what it should have been a decade ago (handlers can throw, errors propagate to error middleware automatically — no more (req, res, next) dance with try/catch in every handler).

TypeScript
import express from "express";

const app = express();
app.use(express.json());

app.get("/api/orders/:id", async (req, res) => {
  const order = await db.order.findUnique({ where: { id: req.params.id } });
  if (!order) return res.status(404).json({ error: "not found" });
  res.json(order);
});

// Async errors propagate automatically in Express 5 — no express-async-errors needed
app.use((err, _req, res, _next) => {
  res.status(500).json({ error: err.message });
});

app.listen(3000);

Why I still ship Express on legacy projects:

  • Hiring market. Every Node.js developer knows Express. Onboarding is zero.
  • Middleware ecosystem. Helmet, CORS, rate limiting, body parsing, file uploads — everything has a maintained Express adapter, including OAuth strategies that Fastify still doesn’t have.
  • Production track record. Express has run more APIs than any other Node framework. The sharp edges are documented; the bug fixes are landed.

What it costs:

  • Slowest of the five at raw throughput. For most APIs that’s irrelevant — you’re bottlenecked on Postgres long before you’re bottlenecked on Express.
  • No native schema validation. You wire up Zod or Joi separately.
  • No first-class TypeScript story. @types/express works but isn’t tight; req.body is any until you cast it. The TypeScript Node.js setup guide covers the config that compensates.
  • Express 5.1 does not change the core architecture. The async fix was the headline; missing TypeScript-first design and missing schema validation are still missing.

Fastify 5 — what I’d ship to a paying client today

If you’re building a new Node.js API in 2026 and the shape is “REST with JSON, talking to Postgres or similar,” Fastify is my default. The schema-driven serialization win is real — fast-json-stringify compiles your response schema once and uses it for every request. The result is the 5× throughput delta in the table.

TypeScript
import Fastify from "fastify";
import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import { Type } from "@sinclair/typebox";

const app = Fastify({ logger: true })
  .withTypeProvider<TypeBoxTypeProvider>();

app.get("/api/orders/:id", {
  schema: {
    params: Type.Object({ id: Type.String() }),
    response: {
      200: Type.Object({
        id: Type.String(),
        customerId: Type.String(),
        total: Type.Number(),
        status: Type.String(),
      }),
    },
  },
}, async (req) => {
  // req.params.id is typed as string — no cast
  return db.order.findUnique({ where: { id: req.params.id } });
});

await app.listen({ port: 3000 });

Why Fastify wins for a senior team:

  • Schema validation and response serialization are first-class — no plugin assembly required.
  • Built-in pino logger. Best-in-class structured logging, no setup. Async transport via worker thread keeps logging off the event loop.
  • Plugin system is genuinely modular. Encapsulation by default; fastify-plugin when you need to break it intentionally.
  • TypeScript types are tighter than Express’s; type generics on routes give you typed params, query, and body from the schema automatically with TypeBox.
  • v5.8.4 shipped two weeks before this article; Express’s last commit was months ago. The maintenance gradient matters over a 5-year project.

What it costs:

  • Smaller community than Express. The middleware ecosystem is mature but not as wide — OAuth strategy coverage in particular lags Passport.js by years.
  • The schema-first API is a real learning curve coming from Express. Expect a week of adjustment.
  • Plugin encapsulation surprises Express developers — a plugin registered inside a fastify.register() scope isn’t available outside it. Use fastify-plugin when you need shared decorators.

Full Fastify-vs-Express benchmark and migration guide in the Express vs Fastify piece.

NestJS — the right answer for 8+ developer teams

NestJS is the framework I’d reach for when the question stops being “how fast is the request handler” and becomes “how do four teams collaborate on the same backend without stepping on each other.” The Angular-flavoured DI, the modules, the explicit boundaries — they’re overhead at small scale and a lifesaver at large.

TypeScript
import { Controller, Get, Param, NotFoundException } from "@nestjs/common";
import { OrdersService } from "./orders.service";

@Controller("orders")
export class OrdersController {
  constructor(private readonly ordersService: OrdersService) {}

  @Get(":id")
  async getOrder(@Param("id") id: string) {
    const order = await this.ordersService.findOne(id);
    if (!order) throw new NotFoundException();
    return order;
  }
}

What you get:

  • Explicit dependency injection. Testing services in isolation is mechanical, not creative.
  • Modules for explicit ownership boundaries. “This is the billing module; here’s its public API.”
  • First-class GraphQL, microservices, queues, scheduling — all official packages, not bolt-ons. NestJS’s GraphQL module wraps Apollo Server — see the GraphQL with Apollo Server guide for the underlying API.
  • Choice of HTTP adapter — Express by default, Fastify if you want the throughput. Switching is one line of bootstrap code and gives you 4× throughput without changing application code.
  • ValidationPipe with class-validator gives type-safe DTO validation per route.

What you pay:

  • Boilerplate. A simple endpoint is a controller, a service, a module, and a DTO. Worth it on a team of 10; overkill on a team of 2.
  • Decorator metadata. The TypeScript compiler dance for emitDecoratorMetadata adds friction in some build setups (esbuild, swc need explicit plugins).
  • You learn NestJS in addition to Node. The ecosystem is somewhat parallel — Nest’s @nestjs/jwt is not jsonwebtoken, etc.
  • Bundle size (~150 kB) is significantly larger than Fastify or Hono. Matters for Lambda cold starts; doesn’t matter for long-lived containers.

If you’ve used Angular professionally, NestJS will feel obvious. If you haven’t, it’ll feel like a lot of indirection at first. Past 8 engineers on the same backend, the indirection is the point.

Hono — the modern choice if you can target modern runtimes

Hono is the framework that made me stop sneering at “edge-first” frameworks. It runs on Node, Bun, Deno, Cloudflare Workers, and Vercel Edge with the same code. The API feels like Express stripped of legacy and tightened up in TypeScript.

TypeScript
import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";

const app = new Hono();

app.get(
  "/api/orders/:id",
  zValidator("param", z.object({ id: z.string().uuid() })),
  async (c) => {
    const { id } = c.req.valid("param"); // typed!
    const order = await db.order.findUnique({ where: { id } });
    if (!order) return c.json({ error: "not found" }, 404);
    return c.json(order);
  }
);

export default app;
// Same code runs on Cloudflare Workers, Bun, Deno, and Node 24

Why I’m reaching for Hono more often:

  • Genuinely fast on Node (128k req/s in this benchmark, 188k on Bun). On the same machine.
  • Tiny dependency footprint. The whole framework is < 12 kB minified.
  • Same code runs on Cloudflare Workers — handy when you want an edge-deployed read API in front of a slower origin.
  • Type safety is excellent throughout. Validation via @hono/zod-validator or the built-in validator is one line per route.
  • Web Standards-first: Request, Response, fetch-style handlers. Skills transfer to Workers, Deno, and the browser.

What’s still rough:

  • Smaller ecosystem than Express or Fastify for Node-specific concerns. @fastify/multipart has more battle-tested file-upload support than Hono’s equivalent.
  • If your hosting is locked to traditional Node, you don’t get the cross-runtime benefit — Fastify is the better Node-only default.
  • Less middleware around enterprise auth (SAML, OIDC) than Express has via Passport.

Elysia — pick this when Bun is the platform

Elysia is Bun’s flagship framework. End-to-end type safety, very fast on Bun’s runtime, opinionated. If you’ve already committed to Bun for production, Elysia is the framework that takes the most advantage of it.

TypeScript
import { Elysia, t } from "elysia";

const app = new Elysia()
  .get("/api/orders/:id", async ({ params, set }) => {
    const order = await db.order.findUnique({ where: { id: params.id } });
    if (!order) { set.status = 404; return { error: "not found" }; }
    return order;
  }, {
    params: t.Object({ id: t.String() }),
  })
  .listen(3000);

The honest call: Elysia is exceptional on Bun. On Node it’s not really the point. And Bun in production in 2026 is still a “yes if your team is comfortable with it” call. The runtime is excellent for development; production support for tooling, observability, and managed hosting is improving but not yet at parity with Node. The full breakdown is in the Node.js vs Deno vs Bun piece.

The decision matrix: pick X when Y

Project shape Pick Why
New API, small-to-mid team, performance matters Fastify 5 Best throughput on Node, schema-first, great TypeScript story
New API, large team (8+ engineers), structure matters more than speed NestJS 11 (Fastify adapter) DI and modules pay back at scale; Fastify adapter buys 4× throughput for free
Existing Express codebase that ships Stay on Express; bump to 5.1 for the security floor Migration cost rarely pays back; v5 closes the async footgun
Edge / serverless / multi-runtime Hono 4 Same code on Node, Bun, Cloudflare Workers, Vercel Edge
Already on Bun, want max throughput Elysia Designed for Bun, end-to-end types
Quick prototype, no perf concerns Express 5 or Hono Fastest to prototype; every dev knows Express, Hono is barely larger
Microservices or distributed system Encore.ts or NestJS microservices Built-in service discovery, infrastructure-from-code
Webhook receiver / OAuth gateway Express 5 Passport.js OAuth strategy coverage is unmatched
Enterprise SSO (SAML, OIDC) Express 5 or NestJS + Express adapter Mature middleware exists; Fastify and Hono have gaps
You’re hiring contractors next week Express 5 or NestJS Largest hiring pool; least onboarding friction

When NOT to use each framework

  • Don’t pick Fastify when: you have zero schema-first experience and a tight deadline (you’ll lose half the perf benefit and pick up a learning curve), you depend on Express-only middleware that isn’t ported (Passport’s full OAuth strategy zoo, some legacy webhook signature verification packages), or you ship to Cloudflare Workers (Fastify can’t run there at all).
  • Don’t pick NestJS when: you’re solo or a team of 2 (the boilerplate slows you down before structure helps), you’re building a small API of < 10 routes, or your team has no Angular / Java / .NET background and dislikes decorators on principle.
  • Don’t pick Hono when: you’re locked to Node-only hosting and need the Node-specific plugin ecosystem (Fastify is better), you need enterprise SSO or Passport-style auth strategies, or your team is allergic to the Web Streams API.
  • Don’t pick Express for new projects when: you have any TypeScript ambitions (the type story will fight you), you need schema validation as a first-class concern, or you care about p99 latency under sustained load.
  • Don’t pick Elysia when: you’re not committed to Bun for production. The framework is great; the runtime is the question.

Migration paths between the three

Express → Fastify: incremental via @fastify/express (full compat, higher overhead) or @fastify/middie (lighter, works for middleware that doesn’t call res.send()). Mount the legacy Express app as a sub-route, migrate one route at a time, decommission Express last. Two-day project for a 20-route API; multi-sprint for a 200-route one. The Express vs Fastify piece walks through the real migration recipe.

Express / Fastify → NestJS: don’t, unless team structure is the actual problem you’re solving. NestJS is a different abstraction (decorators, DI containers); the migration cost is high and the value is organizational, not technical. Better path: keep your existing framework, refactor to NestJS-style module boundaries first, then move when the abstraction earns its place.

NestJS Express adapter → NestJS Fastify adapter: one of the cheapest perf wins in the ecosystem. Single-line bootstrap change, 4× throughput gain on the same controllers. Worth doing the afternoon you decide it.

TypeScript
// NestJS swap from Express to Fastify adapter — application code unchanged
import { NestFactory } from "@nestjs/core";
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
import { AppModule } from "./app.module";

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter({ logger: true })
  );
  await app.listen(3000, "0.0.0.0");
}
bootstrap();

When the framework choice doesn’t matter

For most APIs, the framework is the wrong place to optimize. Pick anything reasonable, ship it, profile when you have real load. Almost every real bottleneck I’ve debugged was the database, the cache, the JSON serialization, or the downstream HTTP call — not the framework’s request handling. Full performance breakdown in the Node.js performance optimization piece. Once you’ve picked a framework, the Jest vs Vitest API testing guide covers the test suite I run on top of any of them.

One specific case where the framework matters less than people think: serverless cold starts. NestJS’s 510 ms cold start sounds bad versus Hono’s 90 ms — but if your Lambda warms up after the first invocation and stays warm for 15 minutes, that 420 ms gap shows up exactly once per warm cycle. For a low-traffic Lambda the gap matters; for anything serving steady traffic the framework’s cold-start number is largely a vanity metric.

FAQ

What is the best Node.js framework in 2026?

Fastify for new APIs that need raw throughput. NestJS for big-team backends that benefit from explicit DI and modules. Hono if you can target modern runtimes (Bun, Cloudflare Workers, Vercel Edge). Express only when the migration cost from an existing Express codebase outweighs the gain. There isn’t one answer; there’s three depending on the project shape.

Express vs NestJS — which is better?

Different answers to different problems. Express is a minimal HTTP layer; you assemble your own architecture on top. NestJS is an opinionated framework with DI, modules, and conventions. For solo developers and small teams, Express is faster to ship. For 8+ engineers on the same backend, NestJS structure pays back. NestJS sits on top of Express (or Fastify); they’re not always either-or.

Is Fastify faster than Express?

Yes — by 5× in this benchmark on a real Postgres-backed API. The win comes from Fastify’s schema-driven response serialization (compiled JSON stringification via fast-json-stringify) and tighter request pipeline. In production with real database queries, the gap shrinks to roughly 1.5–2.5× because most of the latency is the database, not the framework. Full benchmark in the Express vs Fastify comparison.

Should I use Hono in 2026?

Yes if your runtime story is modern — Bun, Deno, Cloudflare Workers, or Node 24+ with a willingness to leave the Express ecosystem. Hono’s API is excellent and the cross-runtime portability is genuinely useful. Skip it if you’re locked to traditional Node hosting and the existing Express ecosystem matters more — Fastify is the better Node-only choice.

Is NestJS overkill?

For a solo developer building a small API, yes. For a team of 10 working on the same backend, no — the structure NestJS imposes is the structure you’d build by hand anyway. Pick by team size and project lifespan, not by feature checkbox. NestJS at 9.1M weekly downloads exceeds Fastify’s 6.7M precisely because enterprise teams find the structure valuable.

What framework does Bun work best with?

Hono and Elysia are both first-class on Bun. Express works but you’re losing Bun’s performance edge to Express’s overhead. If you’re committing to Bun, pick a framework that takes advantage of it. Fastify also runs on Bun but the schema serialization isn’t as well-tuned for Bun’s runtime as it is for Node’s V8.

Is Express dying?

“Dying” is the wrong frame. Express is not getting new adopters at meaningful rates — fewer than 5% of new projects in 2026 reach for it first. But its 92M weekly downloads reflect a decade of production usage and the install base of millions of existing projects, which will stay on Express for years. Express isn’t going anywhere; it’s just no longer the obvious default for greenfield work. Treat it like jQuery — still works, still maintained, no longer the answer for new things.

What about Encore.ts and Nitro?

Both are interesting in 2026. Encore.ts pairs a TypeScript framework with a Rust runtime that handles HTTP parsing outside the event loop, plus declarative infrastructure (databases, Pub/Sub, cron) right in code — strong fit for distributed services. Nitro is the H3-based engine that powers Nuxt 3 and is a credible framework on its own for cross-runtime apps, especially if you’re already in the Vue/Nuxt world. Neither has the install base of the big four yet, but both deserve a serious look if their use case fits.