Why I reach for Hono over Express

Express shaped a generation of Node APIs. Here's why my new backends start with Hono instead, and the three places it actually changes how I build.

PPrabir Singh·
·4 min read
Sunlit walkway through intersecting steel and glass corridors in a modern building.

Express is the framework everyone learns first. It's also the one I quietly stopped starting projects with.

Not because Express is bad. It ran half the internet for a decade and it earned that. But the ground moved. We ship to the edge now. We write TypeScript by default. We expect the thing underneath us to know what a Response actually is. Express predates all of that, and you feel the gap on day one of a fresh build.

Here's the honest version of why my APIs start with Hono now.

The type inference is the whole pitch

With Express, your handler signature is (req, res) and both are mostly any until you bolt on @types and hope. With Hono, the types flow. Your route params, your validated body, your context, all of it is known at compile time.

import { Hono } from "hono"
 
const app = new Hono()
 
app.get("/posts/:id", (c) => {
  const id = c.req.param("id") // string, inferred, no casting
  return c.json({ id })
})

That c.req.param("id") is typed because the route string is part of the type. Rename the param and the compiler catches every reference. That's the difference between finding a bug in your editor and finding it at 2am in production logs.

Validation that carries its own types

Pair it with a schema validator and the inference reaches all the way into your handler body.

import { zValidator } from "@hono/zod-validator"
import { z } from "zod"
 
const schema = z.object({ title: z.string().min(1) })
 
app.post("/posts", zValidator("json", schema), (c) => {
  const body = c.req.valid("json") // { title: string }
  return c.json(body, 201)
})

No manual parsing. No req.body as CreatePostDto. The validated shape is the type.

It runs where I actually deploy

Express assumes Node. Hono assumes the web standard Request and Response, which means the same code runs on Node, Bun, Cloudflare Workers, and a Next.js route handler without a rewrite.

ExpressHono
RuntimeNode onlyNode, Bun, Workers, edge
Base typeCustom req/resWeb Request/Response
Router speedLinear-ishTrie, very fast
Bundle sizeHeavierTiny

When a client's traffic is spiky and global, moving the API to the edge is a config change, not a project. That flexibility has saved me a full migration more than once.

The middleware model stays out of your way

Express middleware mutates req and calls next(). It works, but the data flow is invisible. You never quite know what's on req by the time your handler runs.

Hono middleware is explicit. You set values on the context with a typed key, and you read them back typed. The chain reads like a sentence, and the compiler knows what each step added.

When I still reach for Express

I'm not here to sell you a rewrite. If you have a mature Express app with a team that knows it cold, the framework is not your bottleneck. Ship features. And if you lean on a library that only ships Express middleware, staying put is the cheaper call.

Hono earns its place on new services, edge deploys, and anything where the type safety pays for itself over the life of the codebase. That's most of what I build. It might not be most of what you build, and that's fine.

Frequently asked questions

Is Hono production ready?

Yes. It's used in production at real scale, it's actively maintained, and the API has been stable through its recent major versions. I've shipped client work on it without drama.

Do I have to rewrite my Express app to try it?

No. Hono mounts cleanly inside a Next.js route handler or alongside an existing service. Start with one new endpoint, feel the difference, then decide.

What about the ecosystem?

Smaller than Express, but the essentials are there: validation, auth, CORS, rate limiting. Because it speaks web standards, a lot of platform-native tooling works without a Hono-specific adapter.

Does the edge actually matter for my project?

Only if your users are spread out or your traffic spikes. For a single-region internal tool, the edge is a nice-to-have. The type safety is the reason to switch either way.

The short version

Express taught Node how to serve HTTP. Hono assumes you already know that and hands you type safety, portability, and speed on top. I still respect Express. I just don't start there anymore.

If you're weighing a backend for something new, I wrote about how I pick a stack, and if you want a second opinion on yours, tell me what you're building.

ShareXLinkedIn
P

Prabir Singh

Full-stack engineer from Mumbai. Twenty years in sales, now I build products that sell. More about me or start a project.

Keep reading