Hono vs. H3 vs. HatTip vs. Elysia - modern server(less) replacements for Express
Tags: javascript, webdev, express, serverless
Published: 2024-03-12 10:54:20

Since _"[Express.js](https://expressjs.com/en/starter/hello-world.html) is an old framework that has [not evolved](https://news.ycombinator.com/item?id=38059777) for a long time. It's not a good choice for new projects since it can easily lead to security issues and memory leaks."_ -- [H3](https://h3.unjs.io/examples/from-expressjs-to-h3). Which is also the case for [Koa](https://github.com/koajs/koa/graphs/contributors).

The focus here will be on those frameworks which support [running service workers on the server-side](https://workers.js.org/) and the modern [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) standard, so they can be run in **Serverless and Edge** environments (Cloudflare Workers etc.). So [Fastify](https://fastify.dev/) didn't make the cut for this article, even though it has a 2 year old experiment called [fastify-edge](https://github.com/galvez/fastify-edge). (But they wrote an excellent piece about [the evolution from Node to Worker Environments](https://hire.jonasgalvez.com.br/2022/may/02/the-thing-about-fastify/#what-about-worker-environments) that I recommend reading afterwards.)

> _Worker Runtimes fulfill the original promise of NodeJS: To use one language and share code between client and server. In practice, this never came to be. Instead the APIs of node and browsers have diverged. Worker Runtimes are bringing them back together._ https://workers.js.org/#backend-for-frontend

Hono, H3, HatTip and Elysia are such next generation HTTP server frameworks (aka. web server middlewares). They run everywhere, on any JS runtime, even _Serverless and Edge_ runtimes. Meaning not just on Node.js servers. They are also all TypeScript friendly.

Here's a quick overview of each, and then a comparison of some essential distinctions. (I had to dig up this information from a lot of various sources, so hopefully it's helpful to you all that it's now available here when you Google it.)

All of them have support for the [Web Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) (Request/Response objects). But I'll show their most [Express](https://expressjs.com/en/starter/hello-world.html)-like API's here, for familiarity.

---

<!-- Hono -->

![hono-logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tb7i32mz52qxjks1ok9h.png)

[Hono](https://hono.dev/)'s API is similar to [Express](https://expressjs.com/en/starter/hello-world.html):
```js
import { Hono } from 'hono';

const app = new Hono();
app.get('/hello', (c) => {
  return c.json({ message: 'Hello!' });
});

export default app;
```

Repo started: **[Dec 12, 2021](https://github.com/honojs/hono/graphs/contributors)** - https://github.com/honojs/hono

Main contributors: **[2.5](https://github.com/honojs/hono/graphs/contributors)**

Github stars now: **[12.4 k](https://star-history.com/#unjs/h3&honojs/hono&hattipjs/hattip&elysiajs/elysia&Date)**

NPM weekly downloads now: **[143 796](https://www.npmjs.com/package/hono)**

Current state: Hono is on **[version 4+](https://github.com/honojs/hono/releases)**.

Tagline: _"Fast, Lightweight, Web-standards. Runs on any JavaScript runtime."_

**[Made for Cloudflare Workers first](https://hono.dev/concepts/motivation), but has a Node adapter**. But Hono on Node seems [terribly slow](https://github.com/SaltyAom/bun-http-framework-benchmark). But this is not reflected in the other benchmark: [Web Frameworks Benchmark](https://web-frameworks-benchmark.netlify.app/compare?f=elysia,hono,hono-bun,h3).

Hono is very [web standards focused](https://hono.dev/concepts/web-standard).

Hono has an [RPC feature](https://hono.dev/concepts/stacks#rpc).

Hono aims to have **batteries included**: built-in, custom, and third-party middlewares, and helpers.

---

<!-- H3 -->

![h3-logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b2dhfjey3s4jl7687v2.png)

[H3](https://h3.unjs.io/guide) allows manually registering router instances:
```js
import { createApp, createRouter, defineEventHandler, toNodeListener } from "h3";
import { createServer } from "node:http";

export const app = createApp();
const router = createRouter();
app.use(router);
router.get('/', defineEventHandler((event) => {
    return { message: 'Hello!' };
  }),
);

createServer(toNodeListener(app)).listen(8000);
```

Repo started: **[Nov 15, 2020](https://github.com/unjs/h3/graphs/contributors)** - https://github.com/unjs/h3

Main contributors: **[1.5](https://github.com/unjs/h3/graphs/contributors)**

Github stars now: **[2.9 k](https://star-history.com/#unjs/h3&honojs/hono&hattipjs/hattip&elysiajs/elysia&Date)**

NPM weekly downloads now: **[976 744](https://www.npmjs.com/package/h3)**

Current state: H3 is on **[version 1.11.1](https://github.com/unjs/h3/releases)**.

Tagline: _"The Web Framework for Modern JavaScript Era: H(TTP) server framework built for high performance and portability running in any JavaScript runtime."_

_"H3 is a **composable [and tree-shakeable] framework**. Instead of providing a big core, you start with a lightweight app instance and for every functionality, there is either a built-in utility or you can make yours. Composable utilities have huge advantages comparing to traditional plugin/middleware approaches: ..."_ https://h3.unjs.io/utils

H3 [was extracted](https://github.com/unjs/h3/issues/418#issue-1784595912) from Nitro/Nuxt around Jul 2, 2023 or later. Which may explain the relatively lower amount of github stars.

**Made for Node first, but has [adapters](https://h3.unjs.io/adapters) for Serverless or Edge JS runtimes (Cloudflare Workers etc.)**. [H3 can also run on Bun with an adapter](https://h3.unjs.io/adapters/bun). This is not reflected in the [bun-http-framework-benchmark](https://github.com/SaltyAom/bun-http-framework-benchmark) yet, so follow [this issue](https://github.com/SaltyAom/bun-http-framework-benchmark/issues/64) to see when it's added. Update: In v2 then H3 [will be web native](https://github.com/unjs/rou3/issues/85#issuecomment-2210899189) which suggests that no adapters would be needed.

H3 integrates with the [UnJS ecosystem](https://unjs.io/) of JS tools.

**[NuxtJS](https://nuxt.com/) (Vue meta-framework) is built upon [Nitro](https://nitro.unjs.io/) (http-server extensions) which is built upon H3**. Nitro [adds](https://masteringnuxt.com/nuxt3/lessons/5-16-understanding-nitro) file-based routing, asset handling, storage abstraction, etc. onto H3. (Nitro can selectively use Vite in one of its routing handlers, since Vite is only needed for the client server, not the static server, [according](https://youtu.be/WBH7Ewa--Qg?t=2749) to Nikhil, author of [Vinxi](https://dev.to/this-is-learning/what-is-vinxi-and-how-does-it-compare-to-vike-4883).)

---

<!-- HatTip -->

![hattip-logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01kq0u0e9ndijla88hqq.png)

[HatTip](https://github.com/hattipjs/hattip/tree/main/packages/base/router) also has an Express style imperative routing API:
```js
import { createRouter } from "@hattip/router";
import { json } from "@hattip/response";

const router = createRouter();
router.get("/", () => {
  return json({ message: "Hello!" });
}

export default router.buildHandler();
```

Repo started: **[Feb 20, 2022](https://github.com/hattipjs/hattip/graphs/contributors)** - https://github.com/hattipjs/hattip

Main contributors: **[1.5](https://github.com/hattipjs/hattip/graphs/contributors)**

Github stars now: **[1.1 k](https://star-history.com/#unjs/h3&honojs/hono&hattipjs/hattip&elysiajs/elysia&Date)**

NPM weekly downloads now: **[1 299](https://www.npmjs.com/package/@hattip/core)**

Current state: HatTip is on **[version 0.0.44](https://github.com/hattipjs/hattip/tags)**. (Generally, people consider version 1.0 to represent production-ready.)

Tagline: _"Like Express, but for the future"_.

HatTip should work well with the Vite-based NextJS alternatives [Vike](https://vike.dev/) (aka. vite-plugin-ssr) or [RakkasJS](https://rakkasjs.org/) since HatTip is made by @cyco130 who is behind Rakkas. He collaborates closely with @brillout who is behind Vike and contributes to HatTip. (*Updated for clarity: previously I only said "made by the same guys")

HatTip [integrates with graphql-yoga](https://github.com/hattipjs/hattip#credits).

---

<!-- Elysia JS -->

![elysia-logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d27nu8ssrxseadtznkrg.png)

[Elysia](https://elysiajs.com/) uses chaining / a [fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) for type inference, and gets a distinct style:

```js
import { Elysia } from 'elysia'

new Elysia()
    .get('/json', () => ({
        message: 'Hello!'
    }))
    .listen(8080);
```

Repo started: **[Jul 3, 2022](https://github.com/elysiajs/elysia/graphs/contributors)** - https://github.com/elysiajs/elysia

Main contributors: **[1](https://github.com/elysiajs/elysia/graphs/contributors)**

Github stars now: **[7.1 k](https://star-history.com/#unjs/h3&honojs/hono&hattipjs/hattip&elysiajs/elysia&Date)**

NPM weekly downloads now: **[23 837](https://www.npmjs.com/package/elysia)**

Current state: Elysia released **[version 1.0](https://elysiajs.com/blog/elysia-10.html)** on 16th of March 2024. It was the first stable release after 1.8 years in development. See the [currently latest released version of Elysia here](https://github.com/elysiajs/elysia/releases). (Generally, people consider version 1.0 to represent production-ready.)

Tagline: _"Ergonomic Framework for Humans"_.

Elysia does some advanced [static code analysis](https://x.com/saltyAom/status/1736065679114326355?s=20) (called [Sucrose](https://elysiajs.com/blog/elysia-10.html#sucrose)) which optimizes the performance of your code (by improving the handling of functions).

---

# Comparison:

All of the frameworks are very web standards focused: [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) (the current standard) & [WinterCG](https://wintercg.org/) (the future standard).

## Github stars

![GitHub star history graph for Hono vs. H3 vs. HatTip vs. Elysia as of 2024-03-09](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/osanthgnni5qx9u2oy08.png)

**Hono and Elysia has had a meteoric rise in GitHub stars**.

H3 was extracted from Nitro/Nuxt around Jul 2, 2023 or later. So people might have heard about and starred those higher-level frameworks more than specifically H3. Which may explain the relatively lower amount of GitHub stars for H3 than the others here, even though H3 has been open sourced the longest (since Nov 15, 2020).

For the current up-to-date statistics, see: [GitHub star history graph for Hono vs. H3 vs. HatTip vs. Elysia](https://star-history.com/#unjs/h3&honojs/hono&hattipjs/hattip&elysiajs/elysia&Date).

## NPM downloads

H3 is by far the most downloaded, as seen on [Moiva.io](https://moiva.io/?npm=@hattip/core+elysia+h3+hono), likely because being included with Nitro and NuxtJS (the NextJS of the Vue world):

![NPM downloads of Hono vs. H3 vs. HatTip vs. Elysia as of 2024-03-09](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/db88pex8nkgtwd9xhcz3.png)

If we exclude H3 and zoom in, we see that Hono takes the lead, followed by the younger Elysia, and then HatTip (not yet on v1):

![Zoomed in NPM downloads of Hono vs. HatTip vs. Elysia as of 2024-03-09](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxaf2oer1hsovpb0qe5i.png)

But how is their rate of growth changing? I.e. How fast do they grow?

![NPM downloads monthly growth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypbipin220xpjf7us405.png)

**Hono is currently growing quickest in NPM downloads month-over-month, with 26.6 % growth**. Elysia has 17.9 %, quickly followed by HatTip with 17% and surprisingly **the incumbent H3 at last** with 15.3 % growth in NPM downloads.

For the current up-to-date statistics, see: [NPM and GitHub comparison statistics on Moiva.io for Hono vs. H3 vs. HatTip vs. Elysia](https://moiva.io/?npm=@hattip/core+elysia+h3+hono).


Here is [a log chart that shows their percentage-wise growth compared to their current downloads](https://npmcharts.com/compare/@hattip/core,elysia,hono,h3?log=true). So that their relative growth is easier seen without excluding H3 from the chart due to dwarfing the others. (As a reminder: Logarithmic charts are good for showing trends, long-term perspectives, and a wider range of data compared to linear charts. The key difference from a linear scale is that a logarithmic scale shows percentage changes or orders of magnitude rather than absolute values. Equal vertical distances represent equal percentage changes, not equal absolute changes.)


## Performance and benchmarks

Take all benchmarks with a pinch of salt. More than likely, all of these frameworks will be fast enough for most use cases, and it'll be your app logic that's the bottleneck. With that said, here are some benchmarks (contribute more, and I'll add them).

---

[Web Frameworks Benchmark](https://web-frameworks-benchmark.netlify.app/compare?f=elysia,hono,hono-bun,h3), from [the-benchmarker's github repo](https://github.com/the-benchmarker/web-frameworks). Results in request per second (RPS), and with concurrency 64:

Framework | RPS |
--- | --- |
Hono (Bun) | &nbsp;131 177
H3 (Node?): | &nbsp; 75 422
Hono (Node?): | &nbsp; 68 263
Elysia (Node?): | &nbsp; 64 793

HatTip is [not yet](https://github.com/hattipjs/hattip/issues/114#issuecomment-1986419708) in this benchmark.

---

[fastify-uws helloworld benchmark](https://github.com/Vanilla-IceCream/fastify-uws?tab=readme-ov-file#benchmarks) (using the [Oha](https://github.com/hatoo/oha) to generate the HTTP load for these frameworks):

Framework | RPS |
--- | --- |
Elysia (Bun) | 145 652
Hono (Bun) | &nbsp;117 491
Hono (Node) | &nbsp; 65 704
H3 (Node) | &nbsp; 64 489
H3 (Bun) | &nbsp; 62 165


---

[Denosaurs' helloworld benchmark](https://github.com/denosaurs/bench?tab=readme-ov-file#hello-bench) results was excluded here. Since it didn't have results for either [H3](https://github.com/denosaurs/bench/issues/83) or HatTip, and only [Hono results for Deno](https://github.com/denosaurs/bench/blob/main/frameworks/hono/framework.json). Makes little sense to compare that with [Elysia on Bun](https://github.com/denosaurs/bench/blob/main/frameworks/elysia/framework.json), or with the other benchmarks which are run on other hardware. But now you know about the benchmark, and can improve it by adding these frameworks and/or running it yourself. Let me know if you do, and I can include the results here if you wish.

---

[SaltyAom/bun-http-framework-benchmark](https://github.com/SaltyAom/bun-http-framework-benchmark) (from ElysiaJS author).
- "exercising the same code path repeatedly like in here will show very different performance characteristics compared to a more realistic load profile" and [other tweaking-sensitive issues in the benchmark](https://github.com/hattipjs/hattip/issues/114#issuecomment-1884846698), mentioned by HatTip author. [Corroborated](https://github.com/denosaurs/bench/issues/86#issuecomment-1717710282) by others.
- [biased benchmark when run on windows?](https://github.com/SaltyAom/bun-http-framework-benchmark/issues/48)

Results, in requests per second (RPS), on the repo's official benchmark (ran on an Intel-Core-i7-13700K CPU):

Framework | RPS
--- | ---:|
Elysia (Bun): | 255 574
Hono (Bun): | 203 937
H3 (Node): | &ensp;96 515
Hono (Node): | &ensp;29 036

Some [other guy](https://github.com/SaltyAom/bun-http-framework-benchmark/issues/48#issue-1888510716), running the same test on Linux, on a [generally slower](https://cpu.userbenchmark.com/Compare/Intel-Core-i7-8565U-vs-Intel-Core-i7-13700K/m591977vs4137) machine:

Framework | RPS
--- | ---:|
Elysia (Bun): | 86 841
Hono (Bun): | 73 614

He didn't test the other frameworks.

And [another guy](https://github.com/SaltyAom/bun-http-framework-benchmark/issues/48#issuecomment-1714583623) on Linux, on a [slightly slower](https://cpu.userbenchmark.com/Compare/Intel-Core-i9-13900H-vs-Intel-Core-i7-13700K/m2035047vs4137) CPU than the official benchmark:

Framework | RPS
--- | ---:|
Elysia (Bun): | 199 328
Hono (Bun): | 196 504
H3 (Node): | &ensp;95 482
Hono (Node): | &ensp;20 781

Hono could allegedly be [made about 20 % faster on the Bun benchmark](https://github.com/SaltyAom/bun-http-framework-benchmark/issues/59). Hono on Node seems [terribly slow](https://github.com/SaltyAom/bun-http-framework-benchmark). But this is not reflected in the other benchmark: [Web Frameworks Benchmark](https://web-frameworks-benchmark.netlify.app/compare?f=elysia,hono,hono-bun,h3).

The above tests and info indicate that **Elysia and Hono are about as fast when run on Bun**.

**HatTip is [allegedly](https://github.com/hattipjs/hattip/issues/114#issuecomment-1884846698) about as fast as Hono**, when both are run on Bun.

---

Hono uses a [faster](https://hono.dev/concepts/routers) [RegExpRouter](https://hono.dev/concepts/routers#regexprouter) instead of a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) based router such as [Radix3](https://github.com/unjs/radix3) which H3 uses. But [follow this issue](https://github.com/unjs/h3/issues/692) to see if H3 implements the same RegExpRouter, or [if it is upstreamed to radix3](https://github.com/nksaraf/vinxi/issues/111#issuecomment-1887909864). But in general, it's [likely that the router performance won't matter much](https://github.com/unjs/h3/issues/692#issuecomment-1980663743), since it will be dwarfed by the time it takes to execute user logic.

---

What can be counter-intuitive is that some web frameworks that perform worse on a raw text (i.e. helloworld) response, can perform better than the others when querying a Postgres DB, likely due to specific optimisation. So the rankings can shift, depending on use case.

"If you are looking for the best performing nodejs framework, you should consider that the **performance drops on all frameworks the moment you query a database**. In that scenario, the difference in performance between the fastest and the slowest is reduced and **other factors come into play**." -- [Yet another nodejs benchmark](https://www.pausanchez.com/en/articles/yet-another-nodejs-benchmark/)

## Distinctions / focus

HatTip is [more standards focused than Hono](https://github.com/honojs/hono/issues/443#issuecomment-1455095202). At least when it comes to [universal middlewares](https://github.com/hattipjs/hattip/discussions/45).

HatTip also focuses on:
- [Zero-config CLI](https://github.com/hattipjs/hattip/issues/13)
- [Zero-config library integrations](https://github.com/hattipjs/hattip/issues/18)
- Deep integration With Vite's development server. (Enabling a deeper zero config DX for Vite users.)

Whereas _«Hono is just a web framework. That will not change in the future. No possibility of bundling CLI, at least not at this stage.«_: [according to it's author](https://github.com/honojs/hono/issues/408#issuecomment-1189639299).

HatTip is better suited for (deeper integrated with) Vite than Hono (which requires [plugins](https://github.com/honojs/vite-plugins)).

## Other

Cutting-edge tooling like **[Vinxi](https://dev.to/this-is-learning/what-is-vinxi-and-how-does-it-compare-to-vike-4883)** (used by [Solid Start](https://start.solidjs.com/getting-started/what-is-solidstart) and [Tanstack Start](https://x.com/tannerlinsley/status/1765120904370307438?s=20)) **bets on H3 over Hono:**

> _From Vinxi's perspective, it's way better to bet on H3 which is backed by the Nitro and UnJS teams and is used by Analog and Nuxt. So lot of people working on keep it stable, fast, bug free and working everywhere. (and its still quite a difficult task)._
-- [said](https://github.com/nksaraf/vinxi/issues/111#issuecomment-1887908177) Nikhil Saraf (Vinxi's author).

But it might also be due to other reasons, such as H3 allowing manually registering router instances (which is [Vinxi](https://dev.to/this-is-learning/what-is-vinxi-and-how-does-it-compare-to-vike-4883)'s main feature).

---

Did I forget something important?
Please comment, and I'll try to update the article so the overview is better!

---

Like and share. :) Who else do you think might like it?