DEV Community

Alex Cloudstar
Alex Cloudstar

Posted on • Originally published at alexcloudstar.com

I Tried Hono.js After Years of Express. Here's My Honest Take.

I resisted Hono.js for a long time.

Every month there was another "stop using Express, use Hono instead" post. Another benchmark showing Hono handling four times more requests per second. Another developer on X posting about how they migrated their API and could not believe how clean the code was. I have been around long enough to know that JavaScript framework hype cycles have a short half-life, and I was not about to rewrite a working API because something was trending.

Then I started a greenfield project. New SaaS, new backend, genuinely thinking about what the right stack was. No legacy code to protect. And I figured it was finally time to find out for myself whether Hono deserved the hype or was another JavaScript flavour of the week.

I am glad I tried it.


What Is Hono.js and Why Is It Blowing Up Now

Hono launched in 2022, started as a Cloudflare Workers-first framework, and has spent the last two years quietly becoming one of the fastest-growing Node.js projects on GitHub. In early 2026 it crossed 60,000 stars. TypeScript developers have been talking about it in every corner of the ecosystem -- from Indie Hackers threads to HackerNews to the Bun Discord.

The reason it is gaining momentum now specifically comes down to timing. Two things converged: edge computing went from niche to mainstream, and Express.js entered what is effectively maintenance mode. Express has not had a major release in years. The codebase predates TypeScript, predates modern async patterns, and predates the reality that many production Node.js applications now run in environments where Node.js is not even the runtime.

Hono was built for exactly this moment. It runs natively on Cloudflare Workers, Deno Deploy, Bun, Node.js, and AWS Lambda with the same code. TypeScript is first-class, not bolted on. And it is small -- under 20KB with zero dependencies.

The question is whether "built for the right moment" translates into "right for your project."


What Makes Hono Different at the Core

The architectural difference between Hono and Express is not just marketing language. They are built on different mental models of what a web framework should be.

Express was built in 2010 when Node.js was the only relevant JavaScript server runtime and TypeScript did not exist. Its core is a middleware chain, an HTTP module wrapper, and a router. This is still solid for what it does, but it carries design decisions made for a world that no longer exists.

Hono is built on the WinterCG Web Standards specification. WinterCG (Web-interoperable Runtimes Community Group) is a consortium that defined a common set of Web APIs -- like Request, Response, and Headers -- that every modern JavaScript runtime now implements. When Hono handles a request, it uses these standard Web APIs instead of Node.js-specific types. That is why the same Hono code runs on Cloudflare Workers without an adapter. The runtime speaks the same language the framework speaks.

For developers who have been frustrated by the split between "code that works on Node.js" and "code that works on edge runtimes," this matters a lot. The framework-level impedance mismatch disappears.


The TypeScript Experience Is Night and Day

If you are using Express with TypeScript today, you know the friction. Express was not written for TypeScript. The @types/express package bridges the gap, but it is a retrofit. Route parameters are typed as any unless you manually extend them. Request bodies are any. Query strings are any. The types lie to you constantly and you spend real time asserting your way around them.

Hono's TypeScript support is different because TypeScript was part of the design, not added afterward.

When you define a route in Hono, you can type the path parameters, the request body, the query parameters, and the response -- and those types flow through automatically. The handler knows the type of c.req.param('id') because you told the route what type that parameter has. No casting. No manual type assertions. No lies.

Here is what this looks like in practice:


const app = new Hono()

const route = app.get(
  '/users/:id',
  zValidator('param', z.object({ id: z.string() })),
  async (c) => {
    const { id } = c.req.valid('param')
    // id is typed as string here, validated at runtime
    return c.json({ id })
  }
)
Enter fullscreen mode Exit fullscreen mode

The Zod validator middleware integrates into the type system so that c.req.valid('param') returns the fully validated and typed object. This is TypeScript working correctly because the framework was designed for it -- not fighting against a type definition file that was written as an afterthought.


The Performance Numbers That Actually Matter

Hono benchmarks well. Significantly better than Express in most head-to-head tests.

Independent benchmarks consistently show Hono handling three to four times the requests per second compared to Express under similar conditions, with substantially lower latency. In edge runtime deployments specifically, the gap is even larger because Hono's Web Standards-based core avoids the adaptation overhead that affects frameworks like Express when they run in those environments.

Here is the honest context for those numbers: most web applications are not bottlenecked by their framework's request handling overhead. If your API is slow, it is almost certainly slow because of database queries, external API calls, or inefficient application code -- not because your framework is handling 50,000 requests per second instead of 200,000.

The performance argument for Hono is strongest in specific scenarios: very high-traffic APIs where framework overhead becomes meaningful at scale, edge deployments where bundle size and cold start time matter, and applications where you need maximum efficiency from the first layer of the stack.

For most projects, the framework performance difference will not be your bottleneck. The TypeScript experience and edge compatibility are more practically significant reasons to consider Hono.


Hono's RPC Layer: The Feature Nobody Warned Me About

I expected the performance improvements and the better TypeScript support. What I did not expect was how much I would end up relying on Hono's built-in RPC system.

Hono ships a client package that infers the full type signature of your Hono routes automatically. You define your routes, export the app type, and import it in your client code. The result is a fully typed HTTP client with no code generation step, no schema file to maintain separately, and no schema drift.

Here is what this looks like:

Server:

const routes = app
  .get('/posts', async (c) => {
    return c.json({ posts: [] as Post[] })
  })
  .post('/posts', zValidator('json', postSchema), async (c) => {
    const body = c.req.valid('json')
    return c.json({ post: body })
  })

export type AppType = typeof routes
Enter fullscreen mode Exit fullscreen mode

Client:


const client = hc<AppType>('http://localhost:3000')

const res = await client.posts.$get()
// fully typed: res.json() returns { posts: Post[] }
Enter fullscreen mode Exit fullscreen mode

This is similar to what tRPC does, but without requiring you to adopt tRPC's full framework and mental model. If you want type safety across your client-server boundary without the overhead of a separate RPC layer, Hono's built-in client handles it cleanly.

For projects where tRPC felt like too much overhead and raw fetch with manually maintained types felt too loose, this is the right middle ground.


Where Hono Genuinely Falls Short

I want to be honest about the gaps, because most Hono articles are written by people who are excited about it and undersell the rough edges.

Middleware ecosystem. Express has over a decade of community-built middleware. Rate limiting, session management, authentication, file uploads, request logging, body parsing -- there is a mature, well-maintained package for virtually everything. Hono's ecosystem is growing, but it is smaller. Some things that are a one-liner in Express require more manual work in Hono, or a community package that has 50 stars on GitHub and was last updated eight months ago.

Documentation depth. Hono's official documentation is good for getting started and covers the main features well. But when you get into edge cases -- specific adapter configurations, advanced validator patterns, performance tuning for specific runtimes -- the documentation gets thin fast. You end up in the GitHub issues or the Discord, which is fine but slower than finding the third Stack Overflow answer on the exact problem you are having.

Production debugging. Express's error handling patterns are well understood by the community. Middleware that catches errors, logs them, and formats them for production use is well-documented and widely deployed. I spent more time than expected setting up proper error boundaries and request logging in Hono that matched what I had gotten for free with mature Express boilerplates. It is not hard, just more manual.

Community knowledge base. When I hit an unusual problem with Express, there is almost always a Stack Overflow answer or a GitHub issue that covers exactly my case. Hono's smaller user base means less accumulated knowledge. Not a dealbreaker, but a real tax on debugging time when you hit edge cases.


The Cloudflare Lock-In Question

A concern I had before adopting Hono was vendor dependency. Hono started as a Cloudflare Workers-first framework. Does using Hono mean you are tying your backend to Cloudflare's infrastructure?

The short answer is no, but with nuance.

Hono's multi-runtime support is genuine. A Hono application running on Cloudflare Workers can be migrated to Bun, Deno, or Node.js with minimal code changes -- usually just the entry point and the HTTP server setup. The framework core and your business logic are portable.

The concern is more practical than architectural. If you build your Hono application around Cloudflare Workers-specific features -- KV storage, R2 object storage, Durable Objects, Cloudflare AI -- you are coupling your application to Cloudflare at the infrastructure level, not the framework level. That is a legitimate coupling, but Hono is not the cause. You would have the same coupling if you accessed those APIs from Express.

Hono itself is not the source of lock-in. Your infrastructure choices are. Hono just makes Cloudflare's edge infrastructure easier and more ergonomic to work with, which can lead teams to use more of it than they originally intended. That is worth being aware of as you design your system.


Production Debugging and Observability

This is the area I spent the most unexpected time on, and most articles on Hono skip it entirely.

In Express, adding structured logging, request tracing, and error reporting to production is well-trodden. There are a dozen tutorials for any combination of tools you want. Sentry integration takes five minutes. Morgan or Winston for logging is a known pattern.

In Hono, the pieces exist but the opinionated glue is not there yet. You can use Hono's built-in logger middleware for basic request logging. You can integrate Sentry's Web SDK since Hono uses Web Standard APIs. But assembling a production-grade observability setup -- structured logs with request IDs, error boundaries that capture the full context, trace propagation across services -- required more custom work than I expected.

This is not a framework failure. It is an ecosystem maturity gap. In two years this will probably be as easy as Express. Today it requires more hands-on assembly.

My practical recommendation: if you are running a side project or early-stage product, the manual setup is manageable. If you are deploying a production service at a company with serious observability requirements, budget engineering time for the observability layer that you would not need to budget for with Express.


Should You Migrate Your Express App to Hono?

This is the question I get every time I mention Hono, and it deserves a direct answer.

If your Express application is working, deployed, and maintained: probably not, unless you have a specific reason.

Migration is not free. You have to convert route handlers, replace Express-specific middleware, update your TypeScript types, and retrain your team on the new patterns. For an application that is stable and not hitting Express's limits, the cost is real and the benefit is marginal. You will spend engineer hours on infrastructure work instead of product work, and the result will be a faster framework on a bottleneck that was probably not your actual bottleneck anyway.

The cases where migration makes sense:

You are hitting actual performance limitations and have measured that the framework is the bottleneck. This is rare, but it happens at high traffic volumes.

You are moving to edge deployments -- Cloudflare Workers specifically -- and Express's lack of native edge support is causing real friction.

You are doing a significant rewrite of the application for other reasons and can absorb the migration cost as part of that larger effort.

Your team is frustrated with Express's TypeScript limitations and the productivity improvement from better types justifies the effort.

For greenfield projects, the calculus is different. If you are starting fresh and your team cares about TypeScript, Hono is worth seriously considering. The onboarding cost is lower because there is nothing to migrate, and you start with the better TypeScript experience and edge compatibility from day one. If you are also evaluating full-stack frameworks, the TanStack Start vs Next.js comparison covers the full-stack layer of this same decision.


Hono vs Express: The Decision Framework

Here is how I think about the choice after using both on real projects.

Use Hono for new projects if:

  • You are deploying to edge runtimes (Cloudflare Workers, Deno Deploy)
  • TypeScript correctness matters to your team's daily workflow
  • You want a framework that works identically across multiple runtimes
  • You want the RPC layer for type-safe client-server communication without tRPC
  • Your team is small and comfortable navigating thinner documentation

Stick with Express if:

  • You have an existing Express application that is working well
  • Your team relies on specific Express middleware with no Hono equivalent
  • You need the widest possible ecosystem of community packages
  • Your team is not TypeScript-native and the type inference benefits do not matter to them
  • You want the most documentation, Stack Overflow coverage, and community knowledge

Consider alternatives if:

  • You need a full-featured, opinionated framework with dependency injection: NestJS is still the answer
  • You are optimizing purely for speed on Node.js with a large ecosystem: Fastify is excellent and more mature than Hono
  • You are building on Bun specifically and want to push performance limits: Elysia is worth evaluating

The framework landscape in 2026 is genuinely better than it was even three years ago. Having multiple excellent options with real TypeScript support and edge compatibility is a good problem to have. But it can also lead to spending weeks evaluating frameworks instead of building the product you set out to build.

My honest recommendation: if you are starting fresh and TypeScript matters to your team, try Hono. Build a small feature with it. If it clicks, commit. If it does not, Express will still be there. Just do not let the decision drag on for weeks when you could be shipping instead.


Six Months With Hono

I am still using Hono on the project I started. The initial learning curve was about a week to reach the same productivity I had with Express. The TypeScript experience is noticeably better, and the RPC layer has saved me from an entire category of client-server type drift bugs that I used to catch only in production.

The tradeoffs are real too. I have written more custom middleware than I expected. There was one afternoon lost debugging a request parsing edge case that had fifteen Stack Overflow answers in Express land and nothing in Hono land. The documentation has gaps I filled in by reading the source code directly.

On balance, the switch was worth it for this project. Whether it is worth it for yours depends on factors I cannot know from here -- your deployment target, your team's TypeScript investment, your existing codebase, and whether your actual bottleneck is the framework layer at all.

The tools are good. Pick one and build something.

Top comments (0)