blense.
HomeFrontendCodeAINewsGuidesCheatsheetsAbout

Technology decoded, always.

A curated read on AI, product, and the culture behind the code. No noise, no hype.

blense.

Technology with focus. Stories about what innovation really changes.

Sections

FrontendArtificial IntelligenceCode & DevTech News

Blense

AboutRSSPrivacy policyTermsCookies
© 2026 Blense · blense.fun
Code & Development

Hono.js: The Web Framework You're Probably Not Using Yet — But Should Be

Express was built in 2010. Hono has zero dependencies, runs on any runtime, and processes 4-5x more requests. Here is why the JavaScript ecosystem is migrating.

Gby Genildo SouzaApr 178 min read
Hono.js: The Web Framework You're Probably Not Using Yet — But Should Be

Express was released in 2010. Back then, TypeScript wasn't a mainstream language, edge computing was science fiction, and Cloudflare Workers wasn't even on the horizon.

The JavaScript ecosystem of 2026 is a different world. We have Bun, Deno, Cloudflare Workers, AWS Lambda Edge — each with its own runtime quirks. And we have Hono: a framework built for this world.

2.8 million weekly downloads at the end of 2025 — 340% growth in one year. That's not hype. It's real adoption from teams that tested it and stayed.

Bundle size
12kB
zero external dependencies
Cloudflare Workers
100k+
requests per second
vs Express
4-5×
faster on Node.js

What Hono is

Hono (炎) means flame in Japanese. It was created by Yusuke Wada with a specific goal: a web framework built on Web Standards that runs on any JavaScript runtime — no adapters, no workarounds.

The elite dev's arsenal.
Stop using forEach: 8 semantic array methods to make your JavaScript code readable8 minSolidJS in 2026: Why fine-grained reactivity is outperforming the Virtual DOM27 minTanStack Query: How to Eliminate Manual Server State Management in React6 minStop Using useMemo Wrong: A Practical Guide to React Performance14 min

The core difference from Express: Hono uses the native web platform APIs — Request, Response, fetch. Express uses Node.js's http module, which doesn't exist in other runtimes. That design decision is what makes Hono genuinely multi-runtime.

Hono Web Standards Cloudflare Workers AWS Lambda Node.js Bun Deno Vercel Edge
Diagram — Hono runs on any JavaScript runtime

Getting started

Hono's API will feel familiar if you've used Express before. The difference shows up in the details — and the details are everything.

JS
# For Node.jsnpm create hono@latest my-app# Select: nodejs# For Cloudflare Workersnpm create cloudflare@latest my-app -- --template=hono# For Bunbun create hono my-app
JS
import { Hono } from 'hono'const app = new Hono()app.get('/', (c) => c.text('Hono!'))app.get('/json', (c) => c.json({ message: 'hello' }))app.post('/echo', async (c) => {  const body = await c.req.json()  return c.json(body)})export default app
💡

The c (context) object is the big difference from Express. Instead of two separate req and res parameters, Hono passes everything in a single typed context. c.req for input, c.json() / c.text() / c.html() for output.

Routing and route grouping

Hono's routing system uses a trie-based RegExpRouter — no linear loops. That's what guarantees performance even with hundreds of registered routes.

JS
import { Hono } from 'hono'const app = new Hono()// Route parametersapp.get('/posts/:id', (c) => {  const id = c.req.param('id')  return c.json({ id })})// Query stringsapp.get('/search', (c) => {  const q = c.req.query('q')  const page = c.req.query('page') ?? '1'  return c.json({ q, page })})// Grouping with basePathconst api = new Hono().basePath('/api')// Sub-routers per resourceconst users = new Hono()users.get('/', (c) => c.json([]))users.post('/', async (c) => {  const body = await c.req.json()  return c.json(body, 201)})users.get('/:id', (c) => c.json({ id: c.req.param('id') }))// Mount on the main appapi.route('/users', users)export default api

Middleware

Hono ships built-in middleware for the most common cases — no external packages required. CORS, logger, bearer auth, cache, compression — all available in the main package.

JS
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 middlewareapp.use('*', logger())app.use('*', cors({  origin: ['https://mysite.com', 'http://localhost:3000'],  allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],}))// Route-level middlewareconst token = 'my-secret-token'app.use('/admin/*', bearerAuth({ token }))// Cache on Cloudflare Workersapp.use('/static/*', cache({  cacheName: 'static-assets',  cacheControl: 'max-age=3600',}))// Custom middlewareapp.use('*', async (c, next) => {  const start = Date.now()  await next()  const ms = Date.now() - start  c.header('X-Response-Time', `${ms}ms`)})app.get('/', (c) => c.text('OK'))export default app

Zod validation — the real differentiator

The Zod integration is where Hono shows the difference in developer experience. Define the schema once and get automatic request validation, parsing and TypeScript type inference — all in one shot.

JS
import { Hono } from 'hono'import { z } from 'zod'import { zValidator } from '@hono/zod-validator'const app = new Hono()// User creation schemaconst createUserSchema = z.object({  name: z.string().min(2).max(100),  email: z.string().email(),  age: z.number().int().min(18).optional(),})// Query params schemaconst paginationSchema = z.object({  page: z.coerce.number().int().positive().default(1),  limit: z.coerce.number().int().min(1).max(100).default(20),})app.post(  '/users',  zValidator('json', createUserSchema),  (c) => {    const { name, email, age } = c.req.valid('json')    // name, email, age are fully typed here    // TypeScript knows exactly what they are    return c.json({ id: 1, name, email, age }, 201)  })app.get(  '/users',  zValidator('query', paginationSchema),  (c) => {    const { page, limit } = c.req.valid('query')    // page and limit are already numbers, not strings    return c.json({ page, limit, total: 0, data: [] })  })export default app
ℹ️

When validation fails, Hono automatically returns a 400 Bad Request with the error details. No try/catch, no manual error logic.

RPC Client — end-to-end type safety

This is the feature that surprises people coming from Express the most. Hono ships a built-in RPC client that generates a typed client for calling API routes directly from the frontend — no tRPC, no codegen, no extra configuration.

JS
// server.ts — export the route typesimport { Hono } from 'hono'import { z } from 'zod'import { zValidator } from '@hono/zod-validator'const app = new Hono()const route = app  .get('/api/posts', (c) => c.json([{ id: 1, title: 'Hello' }]))  .post(    '/api/posts',    zValidator('json', z.object({ title: z.string() })),    async (c) => {      const { title } = c.req.valid('json')      return c.json({ id: 2, title }, 201)    }  )export type AppType = typeof routeexport default app
JS
// client.ts — frontend with full type safetyimport { hc } from 'hono/client'import type { AppType } from './server'const client = hc<AppType>('http://localhost:8787')// TypeScript knows the return type of each routeconst posts = await client.api.posts.$get()const data = await posts.json()// data is typed as { id: number; title: string }[]// Compile error if the payload is wrongconst newPost = await client.api.posts.$post({  json: { title: 'New Post' }, // TypeScript validates here})
Frontend hc<AppType>(url) client.api.posts.$get() Hono Server export type AppType = typeof route TypeScript validates payload infers return type HTTP types
Diagram — How the RPC Client works

Native JSX and SSR

Hono supports JSX natively for server-side rendering — no React required, no bundler configuration. Useful for simple pages, transactional emails, or any dynamic HTML.

JS
// app.tsximport { Hono } from 'hono'import type { FC } from 'hono/jsx'const app = new Hono()const Layout: FC = ({ children }) => (  <html lang="en">    <head>      <meta charset="UTF-8" />      <title>My Site</title>    </head>    <body>{children}</body>  </html>)const PostCard: FC<{ title: string; summary: string }> = ({ title, summary }) => (  <article>    <h2>{title}</h2>    <p>{summary}</p>  </article>)app.get('/posts', (c) => {  const posts = [    { title: 'Post 1', summary: 'Summary 1' },    { title: 'Post 2', summary: 'Summary 2' },  ]  return c.html(    <Layout>      <h1>Blog</h1>      {posts.map((p) => <PostCard {...p} />)}    </Layout>  )})export default app

Deploy: same application, different runtimes

Portability is Hono's most important strategic advantage. The same application code runs on any runtime — only the adapter changes.

Node.js

import { serve } from '@hono/node-server' import app from './app' serve({ fetch: app.fetch, port: 3000, }) // package.json // "start": "node dist/server.js"

Cloudflare Workers

import app from './app' // Cloudflare Workers uses // the default export directly export default app // wrangler.toml // name = "my-app" // main = "src/index.ts"

ℹ️

For Bun: export default app directly — Bun recognizes the Hono object natively. Same for Deno and Vercel Edge. The correct adapter is selected by the runtime automatically.

Performance: what the benchmarks say

Express uses Node.js's http module with 13 years of accumulated synchronous middleware overhead. Hono is async-native, uses the Fetch API internally, and has an optimized radix trie router. Less work per request.

Requests / second (higher = better) Hono (Bun) ~850k req/s Hono (Cloudflare Workers) ~100k req/s Hono (Node.js) ~350k req/s Express ~80k req/s
Diagram — Requests per second (comparative benchmark)
⚠️

For most applications, the raw performance difference doesn't change production outcomes — database queries and external calls dominate response time. Hono's real advantage is in cases where the framework itself is on the critical path: API gateways, rate limiting, auth services.

When to use it and when not to

Hono isn't a silver bullet. The choice between it and Express depends on context.

✅ Use Hono when

Greenfield project Edge deployment (Cloudflare Workers) Need multi-runtime (Node + Bun + Deno) TypeScript is a priority Bundle size matters API gateway or performance proxy Small team, no Express legacy

⚠️ Stick with Express when

Legacy codebase with 50+ Express middleware Team already trained and productive in Express Depends on Express-specific libraries Migration cost exceeds the benefit No edge deployment plans

💡

Express to Hono migrations typically take 2 to 4 weeks for typical APIs. The recommended strategy: route by route, starting with read-only endpoints.

What stays with you after reading this
  • 1Hono is built on Web Standards — Request, Response, fetch. That's why it runs on any runtime without adaptation.
  • 2The RegExpRouter is trie-based, not linear loops. That's what delivers 4-5x more performance than Express on Node.js.
  • 3The context c unifies req and res into a single typed object. Less boilerplate, more clarity.
  • 4Zod integration delivers validation, parsing and TypeScript inference from a single schema.
  • 5The RPC Client generates a typed client to call server routes directly from the frontend — no tRPC, no codegen.
  • 6The same Hono app runs on Node.js, Bun, Deno and Cloudflare Workers — only the adapter changes.
  • 7For new projects in 2026, especially with edge deployment: Hono is the correct default.

Express isn't going anywhere. It sustains millions of production applications and will keep getting maintained.

But the next project doesn't need to start in 2010.

Keep reading
Want to go deeper?

Articles on Node.js, TypeScript, API architecture and the modern JavaScript ecosystem — all with real code, no filler.

Explore more on Blueprint Blog

#TypeScript#Node.js#Hono.js#Bun

The elite dev's arsenal.

Microfrontends with Angular and Nx: what nobody tells you
Code & Development

Microfrontends with Angular and Nx: what nobody tells you

Most tutorials show how to build microfrontends in minutes, but few reveal the architectural debt that emerges after months of production deployments.

Genildo Souza · Jul 28 · 15 min
JavaScript Event Loop: The Heart of Non-Blocking Concurrency — Revisited in 2025
Code & Development

JavaScript Event Loop: The Heart of Non-Blocking Concurrency — Revisited in 2025

The Event Loop is not just a simple loop, but a sophisticated coordination mechanism between Call Stack, queues, and runtime. Essential for JS concurrency, it enables thousands of asynchronous operations without blocking the UI. This guide explores its structure, differences between Node.js and browsers, common bugs, advanced techniques, and 2025 trends like Structured Concurrency and scheduler.yield().

Genildo Souza · Jul 26 · 6 min
Next.js 16 PPR: Eliminate the static vs. dynamic tradeoff and achieve Edge TTFB with fresh data
Code & Development

Next.js 16 PPR: Eliminate the static vs. dynamic tradeoff and achieve Edge TTFB with fresh data

Partial Prerendering in Next.js 16 resolves the classic rendering tradeoff, delivering static speed with dynamic data in one seamless response.

Genildo Souza · Jul 13 · 14 min
In this article
  • What Hono is
  • Getting started
  • Routing and route grouping
  • Middleware
  • Zod validation — the real differentiator
  • RPC Client — end-to-end type safety
  • Native JSX and SSR
  • Deploy: same application, different runtimes
  • Performance: what the benchmarks say
  • When to use it and when not to