Express Is 14 Years Old. We Can Do Better.
Express was revolutionary in 2010. But in 2026, it still has no built-in TypeScript support, no native async/await, and middleware ordering bugs that haunt every team.
Hono.js fixes all of this in a 14KB package that runs on every runtime: Node, Bun, Deno, Cloudflare Workers, Vercel, AWS Lambda.
Hello World
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello World"));
app.get("/json", (c) => c.json({ message: "Hello" }));
app.get("/user/:id", (c) => {
const id = c.req.param("id");
return c.json({ id, name: "John" });
});
export default app;
That's it. No require, no app.listen(), no callback hell.
Why It's Better Than Express
| Feature | Express | Hono |
|---|---|---|
| TypeScript | Manual setup | Built-in |
| Bundle size | 200KB+ | 14KB |
| Async handlers | Needs wrapper | Native |
| Validation | Install zod + middleware | Built-in validator |
| OpenAPI docs | Install swagger | Built-in |
| Runtime support | Node only | Node, Bun, Deno, CF Workers, Lambda |
Built-in Validation
No more installing express-validator or zod middleware:
import { Hono } from "hono";
import { validator } from "hono/validator";
const app = new Hono();
app.post("/users",
validator("json", (value, c) => {
const { name, email } = value;
if (!name || typeof name !== "string") {
return c.json({ error: "Name is required" }, 400);
}
if (!email?.includes("@")) {
return c.json({ error: "Invalid email" }, 400);
}
return { name, email };
}),
(c) => {
const { name, email } = c.req.valid("json");
return c.json({ created: { name, email } }, 201);
}
);
Middleware That Makes Sense
import { Hono } from "hono";
import { cors } from "hono/cors";
import { logger } from "hono/logger";
import { bearerAuth } from "hono/bearer-auth";
import { cache } from "hono/cache";
const app = new Hono();
// Global middleware
app.use("*", logger());
app.use("*", cors());
// Protected routes
app.use("/api/*", bearerAuth({ token: "my-secret" }));
// Cached routes
app.get("/api/data", cache({ cacheName: "my-cache", cacheControl: "max-age=3600" }), (c) => {
return c.json({ data: "expensive computation" });
});
All built-in. No npm install for each middleware.
Deploy Anywhere
# Cloudflare Workers
npx wrangler deploy
# Bun
bun run src/index.ts
# Node
npx tsx src/index.ts
# Deno
deno run --allow-net src/index.ts
Same code, any runtime. Write once, deploy anywhere.
Real Performance
Hono consistently benchmarks 2-5x faster than Express on Node.js, and even faster on Bun/Deno since it's designed for modern runtimes.
Requests/sec (simple JSON response):
Express: 18,000
Fastify: 45,000
Hono: 52,000
Hono+Bun: 112,000
Migration From Express
The patterns are almost identical:
// Express
app.get("/users/:id", async (req, res) => {
const user = await db.getUser(req.params.id);
res.json(user);
});
// Hono
app.get("/users/:id", async (c) => {
const user = await db.getUser(c.req.param("id"));
return c.json(user);
});
The main difference: Hono handlers return responses instead of calling res.json(). Cleaner, more functional, easier to test.
Should You Switch?
Yes if you're starting a new project, need edge deployment, or want TypeScript without config.
Not yet if you have a massive Express codebase with custom middleware — migration cost may not be worth it.
But for anything new in 2026? There's no reason to npm init with Express.
I write about modern dev tools and APIs. Follow for more.
More from me: 10 Dev Tools I Use Daily | 77 Scrapers on a Schedule | 150+ Free APIs
Top comments (0)