release · 

H3 v2 beta

⚡ H3 v2 beta is here — fully rewritten on web standards, backward-compatible, and faster than ever!
Pooya Parsa

Pooya Parsa

Visit the new H3 Guide to get started quickly.

H3 started in late 2020, during the rise of edge workers. With H3 + unjs/unenv, we could run Nitro deployments in worker environments with Node.js compatibility, best of both worlds! Since v1.8, H3 has improved its support for web standards.

But still, H3 was primarily based on Node.js APIs with a compatibility layer for web standards. Logical choice at the time, given Node.js's popularity amongst JavaScript server runtimes.

Thanks to evolving web standards by initiatives like WinterTC and runtime support in Deno, Bun, and the latest Node.js, ecosystem is ready to embrace web standards first class for server development. Benefits include:

  • Cross-runtime interoperability (Node.js, Deno, Bun, Workers, etc.)
  • Cross-framework compatibility (H3, Hono, Elysia, etc.)
  • Cross-environment compatibility (shared and familiar code between frontend and backend)
  • Leverage more of runtime native primitives like (Request, URL, Headers, etc.)
  • Easier API testing

💥 Srvx: Universal Web Server API

A major challenge was that Node.js lacks built-in support for web-standard HTTP servers. For node:http compatibility, an adapter is needed to bridge Node.js IncomingMessage to web Request, and to handle web Response via Node.js ServerResponse. We have implemented a compatibility layer that bridges interfaces and achieves up to 96.98% of native node:http performance (see benchmarks).

Runtimes such as Deno, Bun, and Edge Workers pioneered the adoption of web standards for servers, but they did not agree on the same interface due to lack of enough specs. So how do you access the client IP address and additional context? How do you set the server port and TLS options? How do you handle WebSocket upgrades? Each runtime created its own API.

We have created 💥 srvx: A unified layer that works everywhere exactly the same. Compatible with Deno, Bun, Node.js, Service Workers, Edge Workers.

Example
// Dynamic adapter will be used based export conditions of each runtime
import { serve } from "srvx";

serve({
  port: 3000,
  // tls: { cert: "server.crt", key: "server.key" }
  fetch(req) {
    // Server Extensions: req.ip, req.waitUntil(), req.runtime?.{bun,deno,node,cloudflare,...}
    return new Response("👋 Hello there!");
  },
});
With 💥 srvx unifying runtime differences, H3 can remain simpler, focusing exclusively on web standard APIs.

⚡ H3: Tiny Server Composer 🎶

We worked hard to minimize and simplify H3’s scope.

import { H3, serve } from "h3";

const app = new H3().get("/", () => "⚡️ Tadaa!");

serve(app, { port: 3000 });

🪶 Lighter Than a Feather

We approached benchmarking with a new method that focuses on measuring the overhead introduced by the framework itself, rather than the network layer. Our goal is to optimize all relevant measurements together, making the numbers as close as possible to a baseline where no framework is added or used. This method allowed H3 to achieve optimized latency improvements per request and a dramatically smaller core bundle size.

MeasurementH3 v1🚀 H3 v2
Request HandlingNode: 36 µs
Bun: 27 µs
Deno: 7 ms
Node: 7 µs (5x faster)
Bun: 3 µs (9x faster)
Deno: 1.2 µs (156x faster)
Bundle Sizemin: 101 kB
min+gzip: 39.6 kB
min: 9,1 kB (91% smaller)
min+gzip: 3.6 kB (90% smaller)
min: 5.2 kB / min+gzip: 2.1 kB (fetchable handlers)
H3 v2 performance is nearly identical to plain fetch handler with new URL(req.url).pathname for routing. In other words, you get the benefits of H3 with nearly zero performance cost!
Benchmarks apply to the H3 core using the Web Standard target and do not include adapters. They are primarily intended for internal optimization purposes. See the benchmark for details and srvx benchmarks for Node.js adapter performances.

✅ Typed Web Standards

H3 adopts web standard APIs such as Request, Response, URL, and Headers, without introducing new conventions on top of the standards.

We have launched a new initiative to strongly type Web APIs: ✅ fetchdts. Integrated into the H3, now we combine the best of both worlds—standards and the convenience of types.

import { defineHandler } from "h3";

const handler = defineHandler(async (event) => {
  // URL Parsing
  const { pathname, searchParams } = event.url;

  // Access to request headers (try auto-completion in editor!)
  const accept = event.req.headers.get("Accept");

  // Read body
  const bodyStream = await event.req.body;
  const bodyText = await event.req.text();
  const bodyJSON = await event.req.json();
  const bodyFormData = await event.req.formData();

  // Access to runtime specific context
  const { deno, bun, node } = event.req.runtime;

  // Prepare response (h3 does this smartly)
  event.res.headers.set("Content-Type", "application/json");

  return { hello: "web" };
});

Now go ahead and call handler .fetch:

const response = await handler.fetch("/");

// 🧙 Typed response: { hello: string; }
const json = await response.json();
You can directly use event handlers as a standalone, even smaller web handlers without h3 core!

🧩 Middleware and Plugins

H3 now offers an ergonomic, composable way to chain middleware using next() function (inspired by Hono middleware 💛).

Additionally, we have introduced a simple yet powerful pattern to extend H3 apps using reusable plugins.

import { H3 } from "h3";

const app = new H3().use(async (event, next) => {
  // ... before response ...
  const body = await next();
  // ... after response ...
  event.res.headers.append("x-middleware", "works");
  event.waitUntil(sendMetrics(event));
  return body;
});
Accepting next callback is optional. Middleware can be written like v1 without returning a response.

⬆️ Migration from Version 1

We've tried to minimize breaking changes. Most of utilities preserved backward compatibility.

Check out Migration Guide.

🙌 Unified H(TTP) Server Tools for Everyone

H3 and related projects moved to a dedicated github org and new h3.dev domain (thanks to the donation from syntax.fm and other sponsors 💛).

Under the H3 umbrella, we maintain several key components for universal JavaScript servers.

All fully open and usable with or without H3, and with any JavaScript runtime.

❤️ Special Thanks

This release would not have been possible without wonderful contributors, feedback from the community, inspirations from web-standard frameworks including Hono and Elysia, and sponsors who made it possible to work on open source.

🗺️ Roadmap to v2 (stable)

Next steps:

  • Gather feedback from community.
  • Finalize API updates based on feedbacks.
  • Ensure ecosystem compatibility and upgrade for Nitro v3.
Join our Discord to share your experience and feedback!
Visit the new H3 Guide to get started quickly.