Hono vs Express vs Fastify: Node.js Framework Comparison (2026)
Benchmark throughput, latency, and memory across Express, Fastify, and Hono. Compare type safety, middleware ecosystems, edge runtime support, and Zod integration.
Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

Three Frameworks, Three Philosophies
Express has been the default Node.js framework since 2010. Fastify showed up in 2017 promising 2-3x the throughput. Hono landed in 2022 targeting a world where "server" means Cloudflare Workers as often as it means a VPS. In 2026, all three are production-ready -- but they solve fundamentally different problems.
I've shipped services on all three. Express projects that have been humming for years. Fastify APIs where every millisecond of latency mattered. Hono handlers running on five different runtimes without a single line changed. The right choice depends on where your code runs, how much type safety you want, and whether you're building something new or maintaining something old.
What Are These Frameworks?
Definition: Express, Fastify, and Hono are HTTP server frameworks for JavaScript/TypeScript. They handle routing, middleware, request parsing, and response formatting. Express uses a callback-based middleware chain. Fastify uses a plugin system with JSON Schema validation. Hono uses a lightweight handler model designed for portability across Node.js, Bun, Deno, Cloudflare Workers, AWS Lambda, and other runtimes.
All three let you define routes, attach middleware, parse request bodies, and return responses. The differences show up in performance ceilings, type-safety depth, runtime compatibility, and how they handle validation and serialization.
Performance Benchmarks: Throughput, Latency, Memory
Benchmarks were run on a 4-core, 8GB RAM machine (Ubuntu 24.04) using autocannon with 100 connections over 30 seconds. Each framework returned a JSON response from a simple route with no database or I/O.
| Metric | Express 4.21 | Fastify 5.2 | Hono 4.6 (Node) |
|---|---|---|---|
| Requests/sec | 14,800 | 42,600 | 38,900 |
| Avg Latency | 6.7ms | 2.3ms | 2.5ms |
| P99 Latency | 18ms | 5ms | 6ms |
| Memory (RSS) | 82MB | 64MB | 52MB |
| Startup Time | 120ms | 180ms | 45ms |
Fastify leads in raw Node.js throughput thanks to its schema-based serialization using fast-json-stringify. Hono comes close while using less memory -- its minimal core ships at 14KB. Express trails significantly: its middleware chain and lack of built-in serialization optimization add overhead on every request.
When running Hono on Bun instead of Node, throughput jumps to roughly 58,000 req/s. On Cloudflare Workers, cold start times drop below 5ms. These numbers matter when you're paying per-invocation or need sub-10ms response times at the edge.
Pro tip: Real-world performance depends on your middleware stack, database calls, and serialization logic -- not raw framework throughput. A well-optimized Express app will outperform a poorly structured Fastify app every time. These benchmarks show the framework overhead ceiling, not your application's actual bottleneck.
Type Safety: From Minimal to End-to-End
Express: Bolted-On Types
Express was built before TypeScript existed. The @types/express definitions cover the API surface, but request and response types are generic. You end up casting req.body, req.params, and req.query manually. There's no connection between your route definition and the types flowing through your handlers.
import express from 'express';
import type { Request, Response } from 'express';
interface CreateUserBody {
name: string;
email: string;
}
// You must manually type the request -- nothing enforces it
app.post('/users', (req: Request<{}, {}, CreateUserBody>, res: Response) => {
const { name, email } = req.body; // Typed, but not validated
res.json({ id: 1, name, email });
});
The types compile, but nothing validates the incoming data at runtime. You need to add a library like zod, joi, or express-validator separately.
Fastify: Schema-Driven Validation
Fastify uses JSON Schema for request validation and response serialization. With @fastify/type-provider-typebox or @fastify/type-provider-json-schema-to-ts, schemas generate TypeScript types automatically. The schema also drives fast-json-stringify for 2-3x faster JSON serialization.
import Fastify from 'fastify';
import { Type } from '@sinclair/typebox';
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
const app = Fastify().withTypeProvider<TypeBoxTypeProvider>();
const CreateUserSchema = {
body: Type.Object({
name: Type.String(),
email: Type.String({ format: 'email' }),
}),
response: {
200: Type.Object({
id: Type.Number(),
name: Type.String(),
email: Type.String(),
}),
},
};
app.post('/users', { schema: CreateUserSchema }, (req, reply) => {
// req.body is typed AND validated at runtime
const { name, email } = req.body;
reply.send({ id: 1, name, email }); // Response is serialized via schema
});
Hono: End-to-End Type Inference
Hono's type system is its standout feature. Route definitions, middleware, and validators produce a chain of inferred types that flow from the server to a client SDK. Combined with @hono/zod-validator, you get runtime validation and compile-time types from a single Zod schema -- plus a client that knows every route's input and output shapes.
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
const app = new Hono();
const createUserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
const route = app.post(
'/users',
zValidator('json', createUserSchema),
(c) => {
const { name, email } = c.req.valid('json'); // Fully typed + validated
return c.json({ id: 1, name, email });
}
);
// Client-side: types inferred from the route definition
import { hc } from 'hono/client';
type AppType = typeof route;
const client = hc<AppType>('http://localhost:3000');
// client.users.$post({ json: { name, email } }) -- fully typed
This RPC-like client is similar to tRPC, but works over standard HTTP routes. You get typed API calls without code generation or a separate schema definition layer.
Runtime Compatibility: Where Can Your Code Run?
This is where the three frameworks diverge most sharply.
| Runtime | Express | Fastify | Hono |
|---|---|---|---|
| Node.js | Yes (native) | Yes (native) | Yes (adapter) |
| Bun | Compatibility layer | Partial | Yes (native) |
| Deno | Via npm compat | Via npm compat | Yes (native) |
| Cloudflare Workers | No | No | Yes (native) |
| AWS Lambda | Via adapter | Via adapter | Yes (native) |
| Deno Deploy | No | No | Yes (native) |
| Vercel Edge | No | No | Yes (native) |
| Fastly Compute | No | No | Yes (native) |
Express and Fastify are Node.js frameworks. They depend on Node-specific APIs (http module, streams, Buffer) and can't run natively in edge runtimes. Hono builds on the Web Standards API (Request, Response, fetch) which is supported everywhere. Write your Hono app once, deploy it to Cloudflare Workers today and migrate to AWS Lambda tomorrow without changing application code.
Note: "Native" support means the framework is designed and tested for that runtime. "Adapter" or "compatibility layer" means it works through a translation layer that may introduce overhead, subtle behavioral differences, or missing features.
Middleware Ecosystems
| Capability | Express | Fastify | Hono |
|---|---|---|---|
| Ecosystem Size | ~50,000+ npm packages | ~300 official/community plugins | ~80 official middleware + growing |
| Auth | Passport.js (500+ strategies) | @fastify/auth, @fastify/jwt | Built-in JWT, Bearer, Basic |
| CORS | cors package | @fastify/cors | Built-in hono/cors |
| Rate Limiting | express-rate-limit | @fastify/rate-limit | Built-in hono/rate-limiter |
| Static Files | express.static | @fastify/static | hono/serve-static (per-runtime) |
| OpenAPI Generation | swagger-jsdoc (manual) | @fastify/swagger (from schemas) | @hono/zod-openapi (from Zod) |
| Middleware Model | Linear chain (req, res, next) | Plugin encapsulation (register) | Onion model (c, next) -- like Koa |
Express's ecosystem is unmatched in breadth. If a feature exists as an npm package, there's probably an Express middleware for it. Fastify's plugin system is more structured -- plugins encapsulate their routes, decorators, and hooks, preventing the "middleware soup" problem that large Express apps develop. Hono ships the essentials built-in and keeps its middleware lightweight to maintain portability across runtimes.
OpenAPI and Documentation Generation
API documentation matters for team collaboration and consumer onboarding. Each framework takes a different approach:
Express relies on JSDoc annotations parsed by swagger-jsdoc. You write YAML comments above your routes and hope they stay in sync with the actual implementation. They frequently don't.
Fastify generates OpenAPI specs directly from the JSON Schemas you've already defined for validation. Since the schemas drive both validation and documentation, they can't drift. The @fastify/swagger plugin renders Swagger UI automatically.
Hono uses @hono/zod-openapi to generate OpenAPI specs from Zod schemas. You define your route with a Zod schema, and the OpenAPI document is derived from the same source of truth that handles runtime validation and TypeScript inference. One schema, three purposes.
import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi';
const route = createRoute({
method: 'get',
path: '/users/{id}',
request: {
params: z.object({ id: z.string().openapi({ example: '42' }) }),
},
responses: {
200: {
content: { 'application/json': { schema: z.object({
id: z.number(),
name: z.string(),
}) } },
description: 'User found',
},
},
});
const app = new OpenAPIHono();
app.openapi(route, (c) => {
// c.req.valid('param') is fully typed
return c.json({ id: Number(c.req.valid('param').id), name: 'Alice' });
});
// GET /doc returns the generated OpenAPI JSON
app.doc('/doc', { openapi: '3.1.0', info: { title: 'API', version: '1' } });
Edge Runtime: Hono's Unique Advantage
Edge computing means running your code in data centers close to users -- Cloudflare has 300+ locations, Deno Deploy has 35+ regions. Express and Fastify cannot run in these environments because they depend on the Node.js runtime. Hono was designed for this from day one.
Practical implications: a Hono API on Cloudflare Workers has a cold start under 5ms, runs in the data center closest to each user, and scales to millions of requests without provisioning servers. The same code can run on Node.js in a container for workloads that need long-running processes, database connections, or filesystem access.
If your architecture includes any edge deployment -- API gateways, auth endpoints, content transformation, A/B testing logic -- Hono is the only framework in this comparison that supports it natively.
Zod Integration Comparison
Zod has become the de facto validation library in the TypeScript ecosystem. Here's how well each framework integrates with it:
| Aspect | Express + Zod | Fastify + Zod | Hono + Zod |
|---|---|---|---|
| Setup | Manual middleware | zod-to-json-schema + type provider | @hono/zod-validator (first-party) |
| Type Inference | Manual casting | Through JSON Schema bridge | Direct -- Zod types flow to handler |
| Error Formatting | Custom error handler | Custom error handler | Built-in hook for formatting |
| OpenAPI from Zod | Not native | Via zod-to-json-schema | @hono/zod-openapi (native) |
| Client Type Sharing | Manual | Manual | Automatic via hono/client |
Express requires you to write custom middleware to validate with Zod. Fastify converts Zod schemas to JSON Schema under the hood, which works but adds a translation layer. Hono's Zod integration is first-party and seamless -- the Zod schema is the source of truth for validation, types, and OpenAPI documentation with no conversion step.
Frequently Asked Questions
Should I migrate my Express app to Fastify or Hono?
Not unless you have a concrete problem Express isn't solving. Migration costs are real: rewriting middleware, updating error handling, retraining your team. If your Express app is stable and performant enough for your needs, keep it. Invest migration effort only when you're hitting Express's throughput ceiling, need edge deployment capabilities, or are starting a new service where the cost of Express's type-safety gaps is measurable in bugs.
Is Hono production-ready for large-scale applications?
Yes. Hono is used in production by companies running millions of requests per day on Cloudflare Workers, AWS Lambda, and Node.js. Its test suite covers all supported runtimes, and the API has been stable since v3. The ecosystem is smaller than Express, but growing fast -- and most Node.js libraries work with Hono on Node.js since it's just handling HTTP, not replacing the runtime.
How does Fastify achieve 2-3x Express throughput?
Two main optimizations. First, fast-json-stringify compiles JSON Schema into optimized serialization functions at startup, avoiding JSON.stringify's property enumeration on every response. Second, Fastify's routing uses find-my-way, a radix-tree router that's significantly faster than Express's path-to-regexp for route matching. The plugin encapsulation system also avoids the linear middleware chain overhead that Express incurs on every request.
Can I use Express middleware with Fastify or Hono?
Fastify has @fastify/express, a compatibility plugin that lets you use Express middleware inside Fastify. It works for most middleware but adds overhead and loses Fastify's encapsulation benefits. Hono has no Express compatibility layer -- its middleware model is different enough that a wrapper would compromise portability. In practice, most popular Express middleware (CORS, helmet, compression) has a native equivalent in both Fastify and Hono.
What about Elysia, itty-router, and other alternatives?
Elysia is optimized specifically for Bun and delivers impressive benchmarks on that runtime, but it's Bun-only. itty-router is even more minimal than Hono and targets Cloudflare Workers specifically. Koa, created by the Express team, improved on Express's middleware model but never gained the ecosystem momentum to replace it. For a general-purpose comparison, Express, Fastify, and Hono represent the three dominant paradigms: legacy ecosystem, maximum Node.js performance, and multi-runtime portability.
Which framework is best for a REST API with OpenAPI documentation?
Fastify and Hono are both excellent choices. Fastify generates OpenAPI from JSON Schema with @fastify/swagger and has years of production hardening. Hono generates OpenAPI from Zod schemas with @hono/zod-openapi and additionally gives you a typed client. If you're already using Zod elsewhere in your stack (form validation, environment variables, config parsing), Hono's Zod-native approach reduces duplication. If you prefer JSON Schema or need the broader plugin ecosystem, Fastify is the safer bet.
Does Hono work with ORMs like Prisma and Drizzle?
On Node.js, Bun, and Deno -- yes, fully. Prisma and Drizzle work the same way they would in Express or Fastify. On edge runtimes (Cloudflare Workers, Vercel Edge), you need a database driver compatible with that runtime. Prisma Accelerate and Drizzle's HTTP proxy mode solve this, but you're adding a connection proxy layer. If your API is database-heavy and runs on a single runtime, this is not a reason to choose Hono over Fastify -- it's a deployment architecture decision, not a framework one.
Decision Framework
Choose Express when you have an existing Express codebase, need maximum npm ecosystem compatibility, or your team knows Express deeply and the project doesn't warrant retraining. Express is not slow enough to be a problem for most applications, and its middleware ecosystem is unmatched.
Choose Fastify when you need maximum throughput on Node.js, want schema-driven validation and serialization, or are building a large API where plugin encapsulation prevents architecture decay. Fastify is Express's natural successor for teams committed to the Node.js runtime.
Choose Hono when you need edge deployment, multi-runtime portability, end-to-end type inference, or a lightweight framework that stays out of your way. Hono is the right choice for new projects targeting Cloudflare Workers, Lambda@Edge, or any architecture where your code needs to run in more than one environment.
The JavaScript server ecosystem finally has clear lanes. Express for legacy and breadth. Fastify for Node.js performance. Hono for the multi-runtime future. Pick the one that matches where your code actually runs.
Written by
Abhishek Patel
Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.
Related Articles
Top Backend Platforms for SaaS (2026)
Compares backend platforms for SaaS including AWS, Supabase, Firebase, Railway, Render, and bare VPS with real pricing at three scales, multi-tenancy patterns, and build-vs-buy decisions for auth, payments, email, and background jobs.
13 min read
BackendAWS vs Firebase vs Supabase: Backend Platform Comparison (2026)
A comprehensive comparison of AWS, Firebase, and Supabase covering authentication, databases, real-time sync, file storage, serverless functions, and pricing for three app profiles.
12 min read
BackendBun vs Node.js vs Deno: JavaScript Runtime Comparison (2026)
Real benchmarks comparing Bun, Node.js, and Deno on HTTP throughput, file I/O, SQLite, and cold start. Covers npm compatibility, TypeScript support, package management, and enterprise readiness.
12 min read
Enjoyed this article?
Get more like this in your inbox. No spam, unsubscribe anytime.