DEV Community

Cover image for Hono vs. H3 vs. HatTip vs. Elysia - modern server(less) replacements for Express
Magne for This is Learning

Posted on • Edited on

Hono vs. H3 vs. HatTip vs. Elysia - modern server(less) replacements for Express

Since "Express.js is an old framework that has not evolved 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. Which is also the case for Koa. (Update 2024-09-23: After about 10 years in alpha and beta, Express v5.0 was just released)

The focus here will be on those frameworks which support running service workers on the server-side and the modern Fetch API standard, so they can be run in Serverless and Edge environments (Cloudflare Workers etc.). So Fastify didn't make the cut for this article, even though it has a 2 year old experiment called fastify-edge. (But they wrote an excellent piece about the evolution from Node to 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 (Request/Response objects). But I'll show their most Express-like API's here, for familiarity.


hono-logo

Hono's API is similar to Express:



import { Hono } from 'hono';

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

export default app;


Enter fullscreen mode Exit fullscreen mode

Repo started: Dec 12, 2021 - https://github.com/honojs/hono

Main contributors: 2.5

Github stars now: 12.4 k

NPM weekly downloads now: 143 796

Current state: Hono is on version 4+.

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

Made for Cloudflare Workers first, but has a Node adapter. But Hono on Node seems terribly slow. But this is not reflected in the other benchmark: Web Frameworks Benchmark.

Hono is very web standards focused.

Hono has an RPC feature.

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


h3-logo

H3 allows manually registering router instances:



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);


Enter fullscreen mode Exit fullscreen mode

Repo started: Nov 15, 2020 - https://github.com/unjs/h3

Main contributors: 1.5

Github stars now: 2.9 k

NPM weekly downloads now: 976 744

Current state: H3 is on version 1.11.1.

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 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 for Serverless or Edge JS runtimes (Cloudflare Workers etc.). H3 can also run on Bun with an adapter. This is not reflected in the bun-http-framework-benchmark yet, so follow this issue to see when it's added. Update: In v2 then H3 will be web native which suggests that no adapters would be needed.

H3 integrates with the UnJS ecosystem of JS tools.

NuxtJS (Vue meta-framework) is built upon Nitro (http-server extensions) which is built upon H3. Nitro adds 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 to Nikhil, author of Vinxi.)


hattip-logo

HatTip also has an Express style imperative routing API:



import { createRouter } from "@hattip/router";
import { json } from "@hattip/response";

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

export default router.buildHandler();


Enter fullscreen mode Exit fullscreen mode

Repo started: Feb 20, 2022 - https://github.com/hattipjs/hattip

Main contributors: 1.5

Github stars now: 1.1 k

NPM weekly downloads now: 1 299

Current state: HatTip is on version 0.0.44. (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 (aka. vite-plugin-ssr) or RakkasJS 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.


elysia-logo

Elysia uses chaining / a fluent interface for type inference, and gets a distinct style:



import { Elysia } from 'elysia'

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


Enter fullscreen mode Exit fullscreen mode

Repo started: Jul 3, 2022 - https://github.com/elysiajs/elysia

Main contributors: 1

Github stars now: 7.1 k

NPM weekly downloads now: 23 837

Current state: Elysia released version 1.0 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. (Generally, people consider version 1.0 to represent production-ready.)

Tagline: "Ergonomic Framework for Humans".

Elysia does some advanced static code analysis (called 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 (the current standard) & WinterCG (the future standard).

Github stars

GitHub star history graph for Hono vs. H3 vs. HatTip vs. Elysia as of 2024-03-09

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.

NPM downloads

H3 is by far the most downloaded, as seen on Moiva.io, 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

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

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

NPM downloads monthly growth

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.

Here is a log chart that shows their percentage-wise growth compared to their current downloads. 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, from the-benchmarker's github repo. Results in request per second (RPS), and with concurrency 64:

Framework RPS
Hono (Bun)  131 177
H3 (Node?):   75 422
Hono (Node?):   68 263
Elysia (Node?):   64 793

HatTip is not yet in this benchmark.


fastify-uws helloworld benchmark (using the Oha to generate the HTTP load for these frameworks):

Framework RPS
Elysia (Bun) 145 652
Hono (Bun)  117 491
Hono (Node)   65 704
H3 (Node)   64 489
H3 (Bun)   62 165

Denosaurs' helloworld benchmark results was excluded here. Since it didn't have results for either H3 or HatTip, and only Hono results for Deno. Makes little sense to compare that with Elysia on Bun, 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 (from ElysiaJS author).

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):  96 515
Hono (Node):  29 036

Some other guy, running the same test on Linux, on a generally slower machine:

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

He didn't test the other frameworks.

And another guy on Linux, on a slightly slower CPU than the official benchmark:

Framework RPS
Elysia (Bun): 199 328
Hono (Bun): 196 504
H3 (Node):  95 482
Hono (Node):  20 781

Hono could allegedly be made about 20 % faster on the Bun benchmark. Hono on Node seems terribly slow. But this is not reflected in the other benchmark: Web Frameworks Benchmark.

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

HatTip is allegedly about as fast as Hono, when both are run on Bun.


Hono uses a faster RegExpRouter instead of a Radix Tree based router such as Radix3 which H3 uses. But follow this issue to see if H3 implements the same RegExpRouter, or if it is upstreamed to radix3. But in general, it's likely that the router performance won't matter much, 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

Distinctions / focus

HatTip is more standards focused than Hono. At least when it comes to universal middlewares.

HatTip also focuses on:

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.

HatTip is better suited for (deeper integrated with) Vite than Hono (which requires plugins).

Other

Cutting-edge tooling like Vinxi (used by Solid Start and Tanstack Start) 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 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'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?

Top comments (8)

Collapse
 
canrau profile image
Can Rau

HatTip is used in Rakkas which works great for us 🙌
It's actually more built and maintained by the Rakkas creator @cyco130 than the vike (vite-plugin-ssr) creator, they collaborate at times tho from what I understand

Collapse
 
redbar0n profile image
Magne

yeah, that’s true!

Collapse
 
redbar0n profile image
Magne • Edited

Hono is likely a better choice for Cloudflare Workers than using Elysia.

Hono is better at supporting multiple runtimes. Elysia is very Bun focused.

I’m also a bit unsure of the Fluent API style Elysia uses… Such a style has been problematic with tree shaking before, since it uses a mega object, but tree shaking down the bundle size might not matter when you’re only using it on the backend anyway (unless you hit the 1MB limit of CF workers too quickly…).

Elysia author’s own words:

Image description

Collapse
 
redbar0n profile image
Magne • Edited

The team behind H3 implemented a faster router, replacing/renaming radix3 with the new router called rou3.

Benchmark of routers: rou3, radix3, medley, hono-regexp, hono-trie, koa-tree :

Benchmark of routers: rou3, radix3, medley, hono-regexp, hono-trie, koa-tree

github.com/unjs/rou3/pull/107

github.com/unjs/rou3/issues/108

Collapse
 
redbar0n profile image
Magne • Edited

Some old benchmarks made by Medley:

github.com/medleyjs/router-benchmark

With some important note on Benchmark Normalization to ensure fairness:

github.com/medleyjs/router-benchma...

Collapse
 
htmlghozt profile image
Thomas Dillard

I've been searching for this article for a while. This is brilliant thank you.

Collapse
 
ricardogesteves profile image
Ricardo Esteves

Cool article, thanks for sharing it!

Collapse
 
aalvarado profile image
aalvarado

I want to do this combo, Elysia (Bun) thanks for sharing