DEV Community

RAXXO Studios
RAXXO Studios

Posted on • Originally published at raxxo.shop

Hono: The Tiny Framework That Runs My Entire Backend

  • Hono ships under 14KB and runs the same code on Bun, Node, Deno, Cloudflare Workers, and Vercel Edge

  • Cold starts dropped from 380ms on Express to 12ms on Hono plus Cloudflare Workers

  • The RPC client gives end-to-end type safety with zero code generation and zero schema files

  • A typed endpoint with JWT, CORS, and validation fits in 18 lines instead of 60

  • Hono is not the answer for WebSockets-heavy apps or projects that lean on the Express plugin ecosystem

I was writing yet another Express boilerplate at 2am when I finally stopped. Same CORS setup. Same JWT middleware. Same body-parser config. Same 40 lines before I wrote a single business-logic function. I opened a blank file and typed import { Hono } from "hono" instead. That was the last Express project I started.

Seventeen projects. One person writing every line. At that scale, a backend framework is just a time tax. Hono cut mine hard enough that I have not started a new API in anything else for seven months.

Why Hono Replaced Express and Fastify

Express is 15 years old. Fastify is faster but still assumes you are deploying to a long-lived Node server. Neither of them was built for the runtime map I actually ship to. I have APIs running on Bun (local dev and two production services), Node (one legacy service), Cloudflare Workers (four edge APIs), and Vercel Edge (three Next.js route handlers). Moving a handler from one runtime to another used to mean rewriting it. With Hono it means changing the import at the top of the entry file.

Hono was built on Web Standards. Request and Response are the real browser objects, not Node-only wrappers. That sounds academic until you realise it means the exact same handler runs on every modern runtime without a shim. I ported a Vercel Edge endpoint to Cloudflare Workers last week. Three minutes. I changed the adapter import. Nothing else moved.

The raw numbers are where it gets uncomfortable for Express. The Hono core is under 14KB minified. Express with its dependency tree is over 580KB before you install middleware. On Cloudflare Workers, cold starts for my Hono APIs sit at around 12ms. My old Express service (running on a traditional Node host) was 380ms to first response after a sleep. Thirty-two times faster is not a typo. It is what happens when your framework stops pretending every server is a 2010 VPS.

The Stack I Actually Ship

Every new RAXXO API follows the same four-file pattern now. An index.ts that wires the app, a routes/ folder, a middleware/ folder, and a db.ts. No build tool beyond bun build or the Cloudflare Wrangler CLI. Zero config TypeScript because Bun and Workers both understand TS natively.

The middleware story is why this works. Hono ships JWT, CORS, logger, compress, bearer auth, basic auth, cache, CSRF, ETag, rate limiter, and a Zod validator in the box. I install one package. I do not go shopping for cors and helmet and express-rate-limit and pray they still get security updates. The team ships these middlewares on the same release cycle as the core, so a Hono upgrade moves the whole stack forward at once.

Zod validation through the Hono adapter is the single feature that changed my code the most. I used to write a schema, write a validator, write the type, and then write the handler. Now the validator IS the type. If the body fails validation, the request never reaches my handler. If it passes, my handler gets a fully typed object for free. That means roughly 15 lines saved per endpoint and zero runtime type bugs for eight months.

The RPC Client Nobody Talks About Enough

Here is the part that made me delete tRPC from three projects. Hono has a client called hc that reads your server's type signature and gives you a fully typed fetch wrapper on the client. No code generation. No OpenAPI spec. No .proto files. You import the type of your app and you get autocomplete for every route, every param, every response shape.

A real endpoint and its client, top to bottom:


// server.ts
import { Hono } from "hono"
import { jwt } from "hono/jwt"
import { cors } from "hono/cors"
import { zValidator } from "@hono/zod-validator"
import { z } from "zod"

const app = new Hono()
  .use("*", cors())
  .use("/api/*", jwt({ secret: process.env.JWT_SECRET! }))
  .post(
    "/api/posts",
    zValidator("json", z.object({ title: z.string().min(3), body: z.string() })),
    async (c) => {
      const { title, body } = c.req.valid("json")
      const userId = c.get("jwtPayload").sub
      const post = await db.post.create({ data: { title, body, userId } })
      return c.json({ post }, 201)
    }
  )

export default app
export type AppType = typeof app

// client.ts
import { hc } from "hono/client"
import type { AppType } from "./server"

const api = hc("https://api.raxxo.shop")

const res = await api.api.posts.$post({
  json: { title: "New drop", body: "Shipping tonight" },
})
if (res.ok) {
  const { post } = await res.json() // fully typed
}

Enter fullscreen mode Exit fullscreen mode

Eighteen lines for a JWT-protected, CORS-enabled, Zod-validated endpoint plus a typed client. The same thing in Express with express-jwt, cors, express-validator, and a hand-written client wrapper is somewhere around 60 lines across four files and still has no type safety between server and client.

Honest Comparison With Express and Fastify

I am not here to pretend Hono is a religion. Express has 15 years of StackOverflow answers. Fastify has a plugin ecosystem that covers some obscure enterprise cases Hono has not touched yet. If you run a 2000-route monolith with custom streaming protocols and 40 engineers, you are probably not switching frameworks this quarter anyway.

For everyone else, the comparison is not close. On the same Vercel Edge function, Hono serves 1.4x more requests per second than a Fastify equivalent in my benchmarks (simple JSON response, 1000 concurrent connections, three-run median). The bundle shipped to the edge is roughly 40x smaller. Deployment is faster because there is less to upload. Debugging is easier because the stack traces are 3 lines deep, not 30.

The memory story matters too. A Hono Worker handling 100 requests per second holds steady at about 12MB of RAM. The Express service it replaced idled at 80MB and grew to 140MB under the same load. When you pay for memory by the second (Workers, Fly, Railway, Lambda), that difference is real money at the end of the month. I shaved roughly 8€ off one service's bill just by switching frameworks, no other changes.

Express still has one advantage: the sheer volume of tutorials. Every backend course on the internet uses Express. If you are learning HTTP for the first time, that ecosystem of beginner material matters. Once you know how a framework works, Hono's docs are denser and better organised, but the Express tutorial mountain is real.

When I Still Reach For Something Else

Hono does not win every project. Three situations send me elsewhere.

WebSockets-heavy real-time apps. Hono has WebSocket support but it is runtime-dependent and the DX is not as polished as running Bun's native WebSocket server directly or using something like Partykit for rooms and presence. If my app is 80 percent real-time messaging, I skip Hono and go native.

Projects that lean on a specific Express or Fastify plugin. There are a few niche plugins (certain GraphQL federation tools, some legacy SaaS integrations) that only exist for the old frameworks. Porting them is more work than the win from switching. I leave those services alone.

Very large teams with existing Express conventions. Rewriting culture is harder than rewriting code. If a team has 200 Express routes and a style guide that new engineers learn in week one, Hono is a later conversation.

Bottom Line

Hono turned backend work from a chore back into a pleasure. I write fewer lines, ship to more runtimes, and debug less. The RPC client gave me end-to-end type safety without adding a single build step. Cold starts dropped from hundreds of milliseconds to single digits on edge. The whole thing costs nothing and weighs less than the Express logo SVG.

If you are starting a new API this week, try it for one endpoint. Write the same thing twice, once in your current framework and once in Hono. The second one will be shorter, faster, and typed across the wire. That was enough to convert me. Seventeen projects later, I still have not looked back.

RAXXO Studios ships small, fast studio experiments on the RAXXO Lab. See the full stack and products at raxxo.shop, or read how CSS cascade layers changed the frontend side of the same stack.

Top comments (0)