Skip to main content

Express vs Fastify: Node.js Framework Choice 2026

·PkgPulse Team
0

Fastify handles 80,000 requests per second. Express handles 25,000. That's a 3x performance gap — and it's been consistent across every major benchmark since Fastify's release.

But Express still has 76 million weekly downloads. Fastify has 5.4 million. If performance were the only thing that mattered, those numbers would be reversed.

We compared them using real npm data from PkgPulse. Here's the full picture.

At a Glance

MetricExpressFastify
Weekly Downloads76.6M5.4M
Requests/sec20,000–30,00070,000–80,000
First Release20102016
Current Version5.x5.x
TypeScript@types/expressBuilt-in
ValidationManual (middleware)Built-in (JSON Schema)
LoggingManual (middleware)Built-in (Pino)
Async/AwaitSupported (4.x+)Default pattern

See the full live comparison at pkgpulse.com/compare/express-vs-fastify

The headline stat: Fastify is 3-5x faster, but Express has 14x more downloads. Performance and adoption are telling different stories — and both are worth understanding.

Performance: The Numbers

Fastify's speed advantage is real, well-documented, and architectural — not the result of one clever optimization.

  • Synthetic benchmarks: ~80,000 req/sec (Fastify) vs ~25,000 req/sec (Express)
  • Real-world APIs: ~30,000+ req/sec (Fastify) vs ~10,000–15,000 (Express)
  • Extreme scenarios: Some benchmarks show Fastify at 114,000 req/sec — over 5.6x faster

Why the Gap Exists

Four architectural decisions compound:

  1. find-my-way router — Radix-tree-based routing outperforms Express's path-to-regexp by roughly 3x
  2. Schema-based serialization — JSON Schema definitions compile to optimized serialization functions at startup, avoiding runtime reflection
  3. Pino logging — The fastest Node.js logger, using worker threads for I/O instead of blocking the event loop
  4. Plugin system vs middleware chain — Fastify encapsulates plugins rather than walking a per-request middleware stack

When This Actually Matters

For most CRUD APIs serving fewer than 1,000 requests/second, both frameworks handle the load comfortably. The performance gap becomes significant when:

  • High concurrent connections — real-time apps, webhooks, IoT backends
  • Microservices — each service needs to be lean and fast
  • Latency-sensitive APIs — financial services, gaming backends, edge functions
  • Cloud cost optimization — faster response times mean fewer instances. At scale, that's real money.

Developer Experience

Express: Everyone Knows It

Express's API is almost universally familiar:

const express = require('express');
const app = express();

app.get('/api/users/:id', (req, res) => {
  res.json({ id: req.params.id, name: 'John' });
});

app.listen(3000);

Strengths:

  • Minimal onboarding friction — most Node.js developers have used Express
  • Truly minimal — adds almost nothing on top of Node's HTTP module
  • Massive middleware ecosystem: 50,000+ packages on npm
  • Stack Overflow has answers for every Express question you'll ever have

Weaknesses:

  • No built-in validation, logging, or serialization — you assemble these yourself
  • TypeScript via DefinitelyTyped, not first-class
  • Middleware chain ordering can become hard to reason about in large apps
  • Error handling patterns are inconsistent across the ecosystem

Fastify: Structured and Batteries-Included

Fastify provides more out of the box, at the cost of a slightly steeper initial learning curve:

const fastify = require('fastify')({ logger: true });

fastify.get('/api/users/:id', {
  schema: {
    params: { type: 'object', properties: { id: { type: 'string' } } },
    response: {
      200: {
        type: 'object',
        properties: { id: { type: 'string' }, name: { type: 'string' } }
      }
    }
  }
}, async (request, reply) => {
  return { id: request.params.id, name: 'John' };
});

fastify.listen({ port: 3000 });

More verbose — but that schema definition gives you automatic validation, serialized responses (faster JSON output), and auto-generated API docs. The upfront investment pays off.

Strengths:

  • Built-in validation via JSON Schema — validated and serialized automatically
  • First-class TypeScript with type inference from schemas
  • Pino logger included — structured, fast, production-ready
  • Plugin system with proper encapsulation (vs global middleware)
  • Async/await is the default, not an afterthought

Weaknesses:

  • Smaller ecosystem — fewer off-the-shelf plugins than Express
  • Plugin system and decorator pattern have a learning curve
  • Schema-first approach requires upfront investment
  • Fewer community answers (though official docs are excellent)

Ecosystem

Express

Express's ecosystem is unmatched in breadth:

  • Auth: Passport.js (500+ strategies)
  • Validation: express-validator, Joi, Zod (manual integration)
  • ORM: Prisma, TypeORM, Drizzle — all work seamlessly
  • Templating: EJS, Pug, Handlebars
  • Meta-frameworks: NestJS uses Express by default

Fastify

Fastify's ecosystem is smaller but growing steadily:

  • Auth: @fastify/auth, @fastify/jwt, @fastify/passport
  • Validation: Built-in (Ajv + JSON Schema)
  • CORS: @fastify/cors
  • Rate limiting: @fastify/rate-limit
  • API docs: @fastify/swagger — auto-generated from your schemas
  • Meta-frameworks: NestJS supports Fastify as an alternative adapter

One critical bridge: @fastify/express is a compatibility layer that lets you use Express middleware directly in Fastify. This dramatically lowers the migration barrier.

Migration Path

If you're considering moving from Express to Fastify, the pragmatic approach:

  1. Start new services in Fastify — don't rewrite working Express code
  2. Use the compatibility layer@fastify/express mounts Express middleware in Fastify
  3. Migrate route by route — move high-traffic endpoints first for maximum impact
  4. Adopt schemas gradually — start with response schemas (free performance boost), add request validation later

The migration doesn't have to be all-or-nothing. Many teams run both frameworks across a microservices architecture, and that's perfectly fine.

When to Choose Express

  • Your team already knows it — familiarity reduces bugs and speeds development
  • You're prototyping or building an MVP — Express's simplicity gets you to production fastest
  • You need specific middleware that only exists for Express
  • Performance isn't a bottleneck — most apps don't need 80K req/sec
  • You're using NestJS — Express is the default adapter with better documentation

When to Choose Fastify

  • Performance matters — high-throughput APIs, real-time services, microservices at scale
  • You want built-in validation — JSON Schema validation with auto-generated API docs
  • TypeScript is a requirement — first-class types with schema inference
  • You're starting a new project — no Express legacy to maintain
  • Observability is important — Pino logging is genuinely best-in-class
  • You want to reduce cloud costs — 3-5x throughput means fewer server instances

The Verdict

Express is the safe, proven choice. It's the framework most Node.js developers already know, with the largest ecosystem and the most community resources. For most projects, it's perfectly adequate — and "adequate" isn't a criticism.

Fastify is the modern, performance-first choice. For new projects in 2026, it gives you better throughput, built-in validation, superior TypeScript support, and structured logging — all without sacrificing developer experience.

The trend is clear: Fastify's download growth rate is outpacing Express's, and new projects increasingly adopt it as the default. But Express isn't going anywhere — with 76M weekly downloads, it remains the backbone of the Node.js ecosystem for good reason.

Compare Express vs Fastify on PkgPulse →


Frequently Asked Questions

Is Fastify faster than Express?

Yes, significantly. Fastify handles 70,000–80,000 requests/sec compared to Express's 20,000–30,000 under similar conditions. The gap comes from Fastify's radix-tree router, schema-based serialization, and plugin architecture. See the live data on PkgPulse.

Should I switch from Express to Fastify?

Not necessarily. If Express is working for your current load, migration has costs. The pragmatic approach: start new services in Fastify and migrate high-traffic existing routes gradually using the @fastify/express compatibility layer.

What is the fastest Node.js framework?

Among mainstream frameworks, Fastify consistently tops benchmarks at 70,000–80,000 req/sec. Newer frameworks like Hono and uWebSockets.js can be faster in specific scenarios, but Fastify offers the best balance of performance, ecosystem maturity, and developer experience. Compare options at PkgPulse.


Migration Guide

From Express to Fastify

The core routing API is similar; the key differences are plugin registration, schema validation, and async handler syntax:

// Express (old)
import express from "express"
const app = express()
app.use(express.json())

app.get("/packages/:name", async (req, res) => {
  const pkg = await db.findPackage(req.params.name)
  if (!pkg) return res.status(404).json({ error: "Not found" })
  res.json(pkg)
})
app.listen(3000)

// Fastify (new)
import Fastify from "fastify"
const app = Fastify()

app.get<{ Params: { name: string } }>("/packages/:name", async (request, reply) => {
  const pkg = await db.findPackage(request.params.name)
  if (!pkg) return reply.status(404).send({ error: "Not found" })
  return pkg  // Return value is automatically serialized to JSON
})
app.listen({ port: 3000 })

The @fastify/express compatibility plugin allows you to mount Express middleware in Fastify, enabling a gradual route-by-route migration without a big-bang rewrite. Express middleware that inspects req.body works without modification; middleware that calls res.send() or res.json() directly needs adaptation to the Fastify reply API.

Community Adoption in 2026

Express maintains approximately 76 million weekly downloads, the highest of any Node.js HTTP framework by a wide margin. This reflects over 10 years of adoption across millions of projects, tutorials, and textbooks. Express's decline in new project starts does not translate to a decline in downloads, since existing projects on Express continue to install it with every npm install run.

Fastify has grown to approximately 5 million weekly downloads and continues its upward trajectory. Its adoption in new projects — particularly API-only backends, microservices, and NestJS applications using the Fastify adapter — significantly exceeds its raw download share relative to Express. Fastify has replaced Express as the performance benchmark reference for Node.js framework comparisons.

Middleware Ecosystem and Plugin Compatibility

Express's middleware ecosystem and Fastify's plugin system represent fundamentally different approaches to framework extensibility.

Express middleware follows a simple (req, res, next) contract that any function can implement. This simplicity produced a massive ecosystem: helmet for security headers, cors for cross-origin requests, morgan for logging, compression for gzip, express-session for sessions, passport for authentication. These middleware packages are framework-agnostic in principle but optimized for Express's synchronous middleware chain. Using them in Fastify requires either the @fastify/express compatibility layer (which adds overhead) or finding Fastify-native equivalents (@fastify/helmet, @fastify/cors, etc.).

Fastify's plugin system uses fastify-plugin to manage encapsulation — by default, plugins registered in a scope (using fastify.register()) have isolated decorators and hooks. A plugin wrapped with fastify-plugin() breaks encapsulation and shares its decorators globally. This scoping system makes Fastify excellent for organizing large APIs into isolated feature modules, but requires understanding the plugin lifecycle to avoid "decorator not found" errors. The community has ported most common Express middleware to Fastify-native plugins, and the @fastify/* scoped packages are well-maintained by the core team.

TypeScript support differs significantly. Express types in @types/express are functional but were designed for a non-generic API — request body types (req.body) are typed as any by default and require manual type assertions. Fastify uses TypeScript generics throughout: fastify.get<{Params: ParamsType, Body: BodyType}>('/route', handler) produces typed request.params and request.body. This eliminates an entire category of runtime type errors in route handlers and makes Fastify the preferred choice for TypeScript-first codebases in 2026.

For NestJS users: NestJS supports both Express (default) and Fastify as underlying HTTP adapters. Switching from Express to Fastify in NestJS typically requires replacing @nestjs/platform-express with @nestjs/platform-fastify and adjusting middleware registration, but the NestJS application code itself is unchanged. Fastify's performance benefits translate directly to NestJS applications without framework-level changes, making this migration a common optimization for high-throughput NestJS APIs.

A practical consideration for teams choosing between Express and Fastify is the maturity of the deployment ecosystem. Express middleware for AWS Lambda (serverless-http), Google Cloud Functions, and Azure Functions has been available and battle-tested for years. Fastify's @fastify/aws-lambda adapter reaches similar functionality but has a smaller deployment footprint in the community. For teams deploying Node.js APIs to serverless platforms, verifying that the specific platform adapter for Fastify is actively maintained and supports the Fastify version you use is an important pre-migration check that the Express path does not require.

Explore more backend comparisons: Express vs Hono, Fastify vs Hono, or Express vs Koa on PkgPulse.

Related: Decline of Express: What Developers Are Switching To, Express vs Hono in 2026: Legacy vs Modern Node.js, Hono vs Express vs Fastify 2026.

The 2026 JavaScript Stack Cheatsheet

One PDF: the best package for every category (ORMs, bundlers, auth, testing, state management). Used by 500+ devs. Free, updated monthly.