Hono vs Express: Performance Benchmarks on Cloudflare Workers and Node
Source: Dev.to
Benchmark Overview
All tests were run with wrk (12 threads, 400 connections, 30‑second duration) on the same hardware (M3 Pro, 36 GB RAM) using a shared Postgres connection pool (pg, 10 connections) and a single SELECT by primary key per request.
Test route
GET /users/:id – validates a UUID param, runs a single SELECT by primary key, returns JSON.
Results
| Framework | Req/sec | p50 Latency | p99 Latency |
|---|---|---|---|
| Express 4 | 12,400 | 28 ms | 94 ms |
| Fastify 4 | 31,200 | 11 ms | 38 ms |
| Hono 4 | 28,600 | 12 ms | 41 ms |
| Hono 4 + Bun | 41,800 | 8 ms | 27 ms |
Note: Express does not run on Cloudflare Workers (no Node.js runtime). Hono was designed for that environment.
Workers vs. Node
Configuration & Cold Starts
| Environment | Simulated Req/sec | Cold‑start latency |
|---|---|---|
| Hono on Workers | ~45,000 | see example below |
// Example cold‑start handler (Express‑style)
const { id } = req.params;
if (!isValidUUID(id)) {
return res.status(400).json({ error: 'Invalid ID' });
}
const user = await db.users.findById(id);
if (!user) return res.status(404).json({ error: 'Not found' });
res.json(user);
});
app.listen(3000);
Hono (TypeScript)
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
const app = new Hono();
app.get(
'/users/:id',
zValidator('param', z.object({ id: z.string().uuid() })),
async (c) => {
const { id } = c.req.valid('param'); // typed & validated
const user = await db.users.findById(id);
if (!user) return c.json({ error: 'Not found' }, 404);
return c.json(user);
}
);
export default app; // Works on Workers, Bun, Node, Deno
Key Difference
c.req.valid('param')returns typed, validated data.- In Express,
req.paramsis justRecord; validation must be performed manually.
This pattern mirrors the type‑safety of tRPC but for classic REST endpoints.
Middleware Landscape
| Feature | Hono (official) | Express (npm ecosystem) |
|---|---|---|
| CORS, compression, logger, JWT auth, rate limiting, cache headers | ✅ | ✅ (via third‑party) |
| Zod / TypeBox validator | ✅ | ✅ (via third‑party) |
| Static file serving | ✅ | ✅ |
| OpenAPI spec generation | ✅ | ✅ (via swagger-ui-express, etc.) |
| Passport.js | ❌ (no clean port) | ✅ |
express-session | ❌ (use Workers KV / Durable Objects) | ✅ |
| Specialized OAuth middleware | ❌ (some missing) | ✅ |
For greenfield projects, Hono’s official middleware covers ≈ 90 % of typical use cases. When migrating an existing Express app that heavily relies on passport.js or other niche middleware, factor the migration cost.
Portability Example
// src/app.ts – write once
import { Hono } from 'hono';
export const app = new Hono();
app.get('/health', (c) => c.json({ ok: true }));
export default app;
Cloudflare Workers
# wrangler.toml
# point `main` to src/app.ts
// Workers entry (no extra code needed)
export default app;
Node.js
import { serve } from '@hono/node-server';
import { app } from './app';
serve({ fetch: app.fetch, port: 3000 });
Bun
import { app } from './app';
Bun.serve({ fetch: app.fetch, port: 3000 });
The same codebase can run on edge runtimes (Workers, Pages Functions) and on traditional servers, simplifying deployment pipelines.
Decision Guide
- Existing Express app with heavy middleware → Migration cost may outweigh performance gains.
- Team unfamiliar with the Web Request/Response API (Hono’s
c.req/c.res) → Consider training overhead. - Need for Passport.js or other Express‑specific plugins → Stay with Express or find alternatives.
- Greenfield TypeScript API → Use Hono.
- Deployments targeting Cloudflare Workers, Pages Functions, or other edge runtimes → Hono is a natural fit.
- Desire for end‑to‑end type safety without full tRPC adoption → Hono + Zod validator.
- Bun runtime → Hono + Bun currently yields the fastest numbers in our tests.
Performance Considerations
The performance gap between Hono and Express on Node matters only at high concurrency. At a typical production load of ≈ 100 req/sec, user‑facing latency differences are negligible. Choose Hono for its superior developer experience and type safety rather than raw benchmark numbers.
Hono vs. Fastify
Fastify is slightly faster than Hono on pure Node environments, but it does not run on Workers and has a more complex plugin system. When multi‑runtime portability (Workers ↔ Node ↔ Bun) is a priority, Hono is the clear winner.