OMAR
Field NotesCV
Hono: An API That Runs Anywhere
← All Notes
Engineering07 August 2026 · 3 min read

Hono: An API That Runs Anywhere

Built on Web Standards rather than Node APIs, so the same handler runs on Node, Bun, Deno, Cloudflare Workers and Lambda. Small, typed and genuinely fast.

Most Node web frameworks are built on Node's own request and response objects. That was a reasonable choice when Node was the only place server JavaScript ran. It is why moving a service to a Workers runtime or a Bun deployment means rewriting the transport layer.

Hono builds on the Web platform's Request and Response instead. The same handler runs on Node, Bun, Deno, Cloudflare Workers, Vercel and Lambda without changing the code.

The API is unsurprising

import { Hono } from 'hono'

const app = new Hono()

app.get('/health', (c) => c.json({ ok: true }))

app.get('/projects/:slug', async (c) => {
  const slug = c.req.param('slug')       // typed from the route string
  const project = await getProject(slug)
  return project ? c.json(project) : c.json({ error: 'not_found' }, 404)
})

export default app

If you have written Express, you can write this. The difference is that c.req.param('slug') is typed from the route pattern rather than being any, and c.env carries platform bindings with types.

Validation as middleware

import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const lead = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  message: z.string().min(20),
})

app.post('/leads', zValidator('json', lead), async (c) => {
  const data = c.req.valid('json')   // typed and already validated
  await saveLead(data)
  return c.json({ ok: true }, 201)
})

Invalid bodies never reach the handler, and the handler's input type is derived from the schema rather than declared twice. If the same schema is imported by the frontend form, the contract is enforced in one place across the whole stack.

Size is a feature at the edge

The core is tiny — the kind of number that only matters when your code is being instantiated per request in an edge runtime with a cold-start budget. On a traditional long-lived server, framework size is close to irrelevant; on Workers it is the difference between fast and noticeably not.

Where it does not belong

If you have an established Node service with a deep middleware ecosystem — sessions, passport strategies, an ORM's Express integrations — porting for its own sake is not a good trade. Hono is for new services, for edge deployments, and for anything you want to keep portable between hosting decisions you have not made yet.

That last case is the one I hit most on client work: the hosting decision arrives after the code does.

Resources

TypeScriptAPIEdge

Need this built properly?

I build secure, fast, bilingual platforms for clients across Egypt, Saudi Arabia, the UAE and Kuwait.

Keep Reading