Skip to content
Tech Stack4 August 2026 · 9 min read

Hono vs Express vs Bun for SaaS API Servers in 2026

Bun is a runtime, not a framework, so two of these three never competed. Once you separate the runtime pick from the framework pick, the decision gets much smaller.

Hono vs Express vs Bun for SaaS API Servers in 2026

Hono vs Express vs Bun for SaaS API Servers in 2026

A founder asked me last month whether the API for his product should be "on Hono or on Bun." I gave him a bad answer for about thirty seconds before I caught the problem in the question. Two of those three things are not competing with each other at all, and once you separate them the decision gets much smaller.

That confusion is the most common thing I see when someone is picking a backend for a SaaS product. It shows up in job posts, in stack diagrams, in the "what should I learn" threads. So before the benchmarks and the migration horror stories, the boring taxonomy, because everything downstream depends on it. If you want the underlying vocabulary first, my explainer on what a REST API actually is covers the request-and-response layer these tools all sit on top of.

Which of These Three Is Not a Framework?

Two identical brass screwdrivers resting on one side of a chalk line drawn across a beige desk, with a single heavy steel bench vise alone on the other side

Bun is a JavaScript runtime, not a web framework, so it competes with Node.js and Deno rather than with Hono or Express. Hono and Express are the two frameworks in the list. Bun is the thing they can run on, alongside Node. You can run Express on Bun. You can run Hono on Node. The question "Hono or Bun" is closer to "screwdriver or workbench" than to a real fork in the road.

HonoExpressBun
CategoryWeb frameworkWeb frameworkJavaScript runtime
Competes withExpress, Fastify, ElysiaHono, Fastify, KoaNode.js, Deno
HTTP primitiveWeb-standard Request / ResponseNode req / resWeb-standard Request / Response
Where it runsWorkers, Deno, Bun, Lambda, NodeNode.jsIts own process
Minified sizeUnder 14kB (hono/tiny preset)572KBN/A

The size and portability numbers come from Hono's own documentation, which lists Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Netlify, AWS Lambda, Lambda@Edge and Node.js as supported targets. That list is the actual product. Hono is not primarily a faster Express; it is an Express-shaped API that survives being deployed somewhere Node cannot go.

So the real decision is two decisions stacked: which runtime hosts the process, and which framework shapes the handlers. Answer them in that order.

How Fast Is Hono Compared to Express, Really?

A vintage mechanical stopwatch beside a thick rubber hose pinched shut by a black bulldog clip, hard window light throwing the clip's shadow across the paper

Hono handles roughly two to three times the requests per second Express does in hello-world benchmarks, and that gap mostly evaporates once a database is involved. Encore's 2026 comparison of NestJS, Fastify and Hono puts NestJS on the Express adapter at about 28k req/sec, Fastify at about 45k, Hono on Node at about 70k, and Hono on Bun at about 80k. Better Stack's guide independently pegs Fastify at 40,000+ requests per second on a single Node process, which lines up.

Now the part the benchmark charts leave out. Encore's own conclusion on those numbers is that "in practice, your database and network I/O dominate framework overhead." A single unindexed Postgres query costs more milliseconds than the entire routing layer costs microseconds. If your handler does auth, one read, one write and a serialisation pass, you are not measuring Hono against Express anymore. You are measuring your database.

How many requests per second does your API actually serve at peak? If you cannot answer that from a dashboard, the table above is entertainment rather than input.

Where the throughput gap does matter is cold starts and bundle size, which is a serverless concern rather than a server concern. A 14kB framework boots faster in a Worker than a 572KB one, every single time. That is a real argument, and it is a different argument from raw req/s. My glossary entry on serverless walks through why per-invocation startup cost dominates in that model.

Express Is Not Dead, and the Release History Says So

A thick worn cloth-bound ledger open on a desk, its yellowed dog-eared older pages fanned to the left and a crisp blank page waiting on the right

Express 4 shipped a maintenance release on 11 May 2026 and still has active security support, which is not what a dead project looks like. According to endoflife.date's Express tracker, 4.22.2 landed on that date, Express 5.0 arrived on 9 September 2024, and 5.2.1 shipped on 1 December 2025. The framework people keep writing obituaries for is on a normal release cadence.

I bring this up because the migration math is usually worse than the pitch. Hono and Express have genuinely different middleware contracts: Express hands you (req, res, next), Hono hands you (c, next) with a single context object and an awaited next(). There is no official adapter that bridges them. The proposal for one, honojs/hono issue #3293, has been open since 18 August 2024, and the blocker stated in the thread is exactly what you would expect: "Hono's Context object doesn't directly map to Express's req and res objects."

Which means every piece of Express middleware you depend on is a rewrite, a replacement, or a reason not to move. Session handling. Passport strategies. That one custom error handler nobody has read since 2021. Every port I have scoped came in over estimate, and the overrun was in the middleware surface rather than the routes.

None of that makes Express the right pick for a new project. It makes Express a defensible pick for an existing one, which is a claim worth separating from framework fashion.

Where Does Bun Actually Break?

Bun breaks on native addons, and the three that bite backend teams hardest are bcrypt, argon2 and canvas. Most of a typical SaaS dependency tree runs fine. The 2026 Bun compatibility audit by Alex Cloudstar is the most honest inventory I have found, and it is worth reading before you commit a production service.

The short version, with the fixes that exist:

  • bcrypt uses native bindings and does not run. Swap in bcryptjs, or use Bun.password, which is built in and better.
  • argon2 fails for the same reason. You need a pure-JS alternative or the Bun-native path.
  • canvas is broken with, in the audit's words, no clean workaround. If you generate images, invoices or OG cards server-side, this one is a hard stop rather than a papercut.
  • better-sqlite3 is not so much broken as replaced. bun:sqlite ships in core and does the same job.

Also fragile: node:vm and node:cluster are partially supported. If your process model depends on clustering across cores, test that specifically before you plan around it.

Bun 1.3 Made the Framework Question Smaller

The most interesting recent change is not on the framework side at all. Bun 1.3, released 10 October 2025, pulled a pile of things into the runtime that used to require dependencies: Bun.serve() gained parameterized :id routes, catch-all routes and method-specific handlers, and the runtime now ships a unified Bun.SQL client covering Postgres, MySQL, MariaDB and SQLite, plus a Redis client with 66 commands that the release notes clock at 7.9x the throughput of ioredis.

Read that as a strategy, not a feature list. For a small internal service with a dozen endpoints, Bun 1.3 removes the reason to install a framework in the first place. Routing, database access and caching all come from the runtime. That is a genuinely new option in this comparison and it did not exist eighteen months ago.

It does not scale up gracefully, though. The moment you want composable middleware, typed route groups, request validation and an RPC client, you want Hono. Bun's router is a router. Hono is a framework, and the difference shows up around endpoint thirty.

The Testing Story

This is where Hono quietly wins. app.request(path, options, env) builds a Request, passes it straight to your app, and hands back the Response — no server to boot, no supertest, no port. Hono's testing guide shows the whole API in about four lines. Express testing is fine. It is just never this small.

Mounting Hono Inside Next.js

If you are already on Next.js, Hono replaces route handlers rather than sitting beside them. The setup, per Hono's Next.js guide:

  1. Create app/api/[[...route]]/route.ts. The optional catch-all segment is what lets one file own every API path.
  2. Instantiate with a base path: const app = new Hono().basePath('/api').
  3. Define routes on that instance the normal way, with .get(), .post() and friends.
  4. Export the method handlers: export const GET = handle(app) and export const POST = handle(app), where handle comes from hono/vercel.

What you get out of it is a real router with middleware composition instead of one file per path, and end-to-end types via Hono's RPC client if you use the validator. That second part is the actual draw for me, and it only pays off if your codebase is typed end to end already.

How I'd Pick This Week

For a new SaaS API where you control the runtime, I would start on Hono and run it on Bun, and I would not treat that as a permanent commitment. Hono's web-standard handlers move to Node, Workers or Lambda later without a rewrite, which is the cheapest optionality available in this category. If any dependency needs a native addon, run the same Hono app on Node instead and lose nothing but a few thousand req/s you were never going to notice.

For an existing Express service that works: leave it. Express 5 is maintained, your middleware is paid for, and the migration will cost more than the benchmark delta returns.

There is a third case that is easy to forget. Sometimes the framework decision does not exist. On BookBed, the entire server-side HTTP surface that ever mattered was the Stripe webhook that keeps accountType in lockstep with subscription status, and Firebase owned that endpoint. No framework was chosen because none was needed. Actually, let me be more precise: a framework decision was made, by the platform, before I got a vote. That is a normal outcome for a product where the client does most of the work, and it is worth checking whether it describes yours before you spend a week on this comparison. The SaaS MVP stack guide walks the same decision from the other direction, starting from the product rather than the runtime.

So: go open your APM and find your p95 for one real endpoint, then find what share of it is spent outside your database. If that share is under ten percent, you already know which of these three questions is worth your afternoon. Which one is it?

Free resource

Free SaaS MVP Scope Template

A Notion document with the full feature checklist, MVP vs. nice-to-have table, pre-build questions, and cost signals — so you walk into any developer call knowing exactly what to ask for.

Get the template →
DL

Dusko Licanin

Full-Stack Developer · Banja Luka, Bosnia

Full-stack developer shipping SaaS MVPs, web apps, and mobile apps using AI-augmented workflows — without agency coordination overhead. Live portfolio: BookBed, Callidus, Pizzeria Bestek.

Frequently Asked Questions

Should I use Hono for Next.js API routes?

Hono is worth it in Next.js once your API outgrows one file per path. You mount it at app/api/[[...route]]/route.ts using an optional catch-all segment, instantiate with basePath('/api'), and export the method handlers via handle from hono/vercel. What you gain over plain route handlers is real middleware composition and end-to-end types through Hono's RPC client when you pair it with the validator. For an API with five endpoints, plain route handlers are fine and the extra dependency is not earning its place. The switch pays off somewhere around endpoint fifteen, when directory structure stops matching how you want to group routes.

Is Bun ready for a production API server?

Bun is production-ready for API servers that avoid native addons, which covers most TypeScript backends using Prisma, Drizzle or a pure-JS driver. The failure mode is dependency-shaped rather than stability-shaped. bcrypt, argon2 and canvas all rely on native bindings and do not run, and canvas has no clean workaround, so server-side image or PDF generation is a hard blocker. Audit your dependency tree before you commit, not after. Bun 1.3 also pulled routing, a unified SQL client and Redis into the runtime itself, so a small service can now ship with no framework dependency at all.

What backend framework should a new SaaS start with?

Start on Hono if you control the runtime, because its web-standard handlers move between Node, Bun, Workers and Lambda without a rewrite. That portability is the cheapest optionality available in this category, and you buy it for a 14kB dependency. Express is the better answer only when you are extending something that already runs on it, where the existing middleware is already paid for. Fastify sits between the two and is a reasonable pick if you are staying on Node forever and want maximum throughput per process. The framework matters far less than whether your database queries are indexed.

What are the real alternatives to Express in 2026?

The three serious alternatives are Hono, Fastify and Elysia, and they differ mainly in which runtime they optimise for. Hono targets portability across Node, Bun, Deno and edge runtimes using web-standard Request and Response objects. Fastify targets peak throughput on Node specifically, with a mature plugin ecosystem and schema-based validation. Elysia is Bun-first and leans hardest into type inference. Express itself is not out of the running: version 4.22.2 shipped in May 2026 and 5.x is under active maintenance, so "Express is dead" is a marketing line rather than a release-history fact.

Can I migrate from Express to Hono incrementally?

Yes, and incrementally is the only sane way, because there is no official adapter that runs Express middleware inside Hono. The request contracts genuinely differ: Express hands you (req, res, next) while Hono hands you a single context object and an awaited next(). Start by porting stateless JSON routes, which usually convert almost mechanically, and run both apps behind one reverse proxy while you go. Save session handling, Passport strategies and custom error middleware for last, because that surface is where every migration I have scoped ran over its estimate. Routes are the easy part.