NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #1303 most downloaded on npm
Node.js Adapter for Hono
Last release 6 days ago
29 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 58 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
103 releases · first in 2023
One column per quarter.
serveStatic decodes the request path a second time, leading to bypass of middleware on static paths
serveStatic decodes the request path a second time, leading to bypass of middleware on static pathsAffects: @hono/node-server/serve-static. Fixes serveStatic decoding an already-decoded path, where a crafted request could be routed as one path and served as another, skipping middleware mounted on a static prefix. GHSA-rmxm-3fg6-px4f
serveStatic now rejects request paths that still contain % after decoding. To serve files whose names contain a literal %, set allowPercentInPath: true.
The same fix ships in hono v4.13.11.
ci: add autofix.ci by @yusukebe in #392
Full Changelog: v2.1.1...v2.1.2
perf: lazily materialize request headers by @BlankParticle in #389
Full Changelog: v2.1.0...v2.1.1
feat: add Early Hints (HTTP 103) middleware by @bilal-azam in #378
Full Changelog: v2.0.12...v2.1.0
test: replace supertest by @BlankParticle in #379
Full Changelog: v2.0.11...v2.0.12
test: use a custom helper for path traversal tests by @BlankParticle in #377
Full Changelog: v2.0.10...v2.0.11
This release includes a fix for the following security issue:
This release includes a fix for the following security issue:
Affects: upgradeWebSocket. A WebSocket upgrade request with a missing or malformed Sec-WebSocket-Key header leaked the request's IncomingMessage and left a promise pending, even though no connection was established. Since the route is reachable pre-handshake without authentication, an attacker could flood it to gradually exhaust memory. GHSA-9mqv-5hh9-4cgg
Users of upgradeWebSocket are encouraged to upgrade to this version.
fix(websocket): polyfill missing ErrorEvent global by @otnc in #371
ci(release): add --no-git-checks option for pnpm stage publish by @yusukebe in #369
Full Changelog: v2.0.7...v2.0.8
ci: publish to npm from CI with OIDC trusted publishing and bump np by @yusukebe in #361
Fixed a security issue in Serve Static Middleware where prefix-mounted middleware could be bypassed on Windows. This only affects applications running
Fixed a security issue in Serve Static Middleware where prefix-mounted middleware could be bypassed on Windows. This only affects applications running on Windows that use Serve Static Middleware. Affected users are encouraged to upgrade to this version.
See GHSA-frvp-7c67-39w9 for details.
fix: stub ws types to prevent them leaking in public types by @BlankParticle in https://github.com/honojs/node-server/pull/359
Full Changelog: https://github.com/honojs/node-server/compare/v2.0.3...v2.0.4
chore(ci): update GitHub Actions versions by @BlankParticle in https://github.com/honojs/node-server/pull/352
ServeStaticOptions comment with the current spec by @kakkokari-gtyih in https://github.com/honojs/node-server/pull/356Full Changelog: https://github.com/honojs/node-server/compare/v2.0.2...v2.0.3
fix(serve-static): stop using file birthtime for Date header by @usualoma in https://github.com/honojs/node-server/pull/350
Full Changelog: https://github.com/honojs/node-server/compare/v2.0.1...v2.0.2
fix: forward Hono response headers during WebSocket upgrade by @gentamura in https://github.com/honojs/node-server/pull/346
Full Changelog: https://github.com/honojs/node-server/compare/v2.0.0...v2.0.1
There are two breaking changes in v2.
Now, we release the second major version of the Hono Node.js adapter 🎉 🎉 🎉
v2 of the Hono Node.js adapter reaches up to 2.3x the throughput of v1 — that's the peak number, measured on the body-parsing scenario of bun-http-framework-benchmark. The other scenarios (Ping, Query) get a smaller but real boost too.
Install or upgrade with:
npm i @hono/node-server@latest
The Node.js adapter is going through a major version bump to v2. That said, the public API stays the same — the headline of this release is the large performance improvement described above.
A quick refresher on what the Node.js adapter actually does — it exists so that Hono applications can run on Node.js. Hono is built on the Web Standards APIs, but you cannot serve those directly from Node.js. The adapter bridges the Web Standards APIs and the Node.js APIs, which is what lets a Hono app — and more generally a Web-Standards-style app — run on top of Node.js.
If you write the following code and run node ./index.js, a server starts up on localhost:3000. And it really is plain Node.js underneath.
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
const app = new Hono()
app.get('/', (c) => c.text('Hello World!'))
serve(app)
The very first implementation of the Node.js adapter looked roughly like this in pseudocode:
export const getRequestListener = (fetchCallback: FetchCallback) => {
return async (incoming: IncomingMessage, outgoing: ServerResponse) => {
const method = incoming.method || 'GET'
const url = `http://${incoming.headers.host}${incoming.url}`
// ...
const init = {
method: method,
headers: headerRecord,
}
// app is a Hono application
const res = await app.fetch(new Request(url, init))
const buffer = await res.arrayBuffer()
outgoing.writeHead(res.status, resHeaderRecord)
outgoing.end(new Uint8Array(buffer))
}
}
So the flow was:
IncomingMessageRequest object and handed to the appResponse returned by the app is written back to the outgoing ServerResponseIn diagram form:
IncomingMessage => Request => app => Response => ServerResponse
This is, frankly, inefficient. So whenever Hono went head-to-head with other Node.js frameworks we kept losing — all we could do was shrug and say "well, it's slow on Node.js."
The huge step forward that fixed this was a legendary PR from @usualoma:
https://github.com/honojs/node-server/pull/95
It made things up to 2.7x faster.
I previously wrote about this in detail in this post:
https://zenn.dev/yusukebe/articles/7ac501716ae1f7?locale=en
In short, the trick is wonderfully simple. It just follows the golden rule of performance tuning: don't do work you don't have to do. Lightweight versions of Request and Response are constructed and used first — and that path is fast. Only when something actually needs the contents of the Request, e.g. when you call req.json(), does a real new Request() get instantiated under the hood and used from then on. The result is fast, and behavior stays correct.
"Fast" here was for a very simple "Hello World" benchmark — a GET that just returns text.
There are many ways to benchmark, but the one we tend to reach for is this:
https://github.com/SaltyAom/bun-http-framework-benchmark
It tests three scenarios: Ping, Query, and Body. Let's pit Hono against the major Node.js frameworks:
As you can see, the Body case is very slow. The handler being measured is essentially this:
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
const app = new Hono()
app.post('/json', async (c) => {
const data = await c.req.json()
return c.json(data)
})
serve(app)
c.req.json() is the slow part. The reason is well understood: inside the Node.js adapter, when json() is called the LightweightRequest path can't be used, so a real new Request() ends up being constructed.
The 2.3x figure above comes from one PR specifically — PR #301 by @mgcrea:
The PR bundles a few changes, but the key one is "optimize request body reading". Quoting from the PR description:
The fix overrides
text(),json(),arrayBuffer(), andblob()on the request prototype to read directly from the Node.jsIncomingMessageusing event-based I/O.
In other words, in the json() case above, we no longer convert into a Request at all — we read the body straight off the Node.js APIs. A classic fast path. That alone gives a large jump in body-parsing throughput.
The same PR also includes two other tuning improvements:
URL object except in edge casesbuildOutgoingHttpHeaders optimization — skip the set-cookie header comparison when there are no cookiesv2 ships several other performance PRs as well — newHeadersFromIncoming and signal fast-paths, Response fast-paths and responseViaCache improvements, method-key caching, a regex-based buildUrl rewrite, and more (see the full list below). They all add up, but #301 is by far the largest single contributor, which is why it gets the spotlight here.
Now let's measure the final v2 build.
First, comparing against the v1 Node.js adapter. dev here is v2. Body improves by 2.3x, and the other scenarios get faster too:
Next, the same comparison against other frameworks. With the Body score jumping, Hono passes Koa and Fastify and takes first place:
[!CAUTION] Updated: The h3 entry in the earlier framework comparison was an older snapshot. Its successor
srvxnow ships aFastResponsemode, and in srvx's own benchmark (h3js/srvx/test/bench-node)srvx-fast(≈68,560 req/sec) beatshono-fast(≈59,477 req/sec). The methodology is different from the benchmarks above, but worth being upfront: withFastResponseenabled,srvxis faster than Hono v2 in that setup.
There are two breaking changes in v2.
Node.js v18 reached end-of-life, so v2 requires Node.js v20 or later.
The Vercel adapter (@hono/node-server/vercel) has been removed. It is no longer needed for Vercel's modern runtimes, so the recommendation is to deploy without it.
If you still need the previous behavior, the old adapter was a one-liner on top of getRequestListener and you can write the same thing in your own project:
import type { Hono } from 'hono'
import { getRequestListener } from '@hono/node-server'
export const handle = (app: Hono) => {
return getRequestListener(app.fetch)
}
Then use it the same way you used handle from @hono/node-server/vercel before.
A full list of what landed in PR #316.
buildOutgoingHttpHeaders for the common case (#301) by @mgcrea: as safe host (#320) by @yusukebenewHeadersFromIncoming and signal fast-path (#332) by @GavinMeierSonosResponse fast-paths and responseViaCache improvements (#333) by @GavinMeierSonosUint8Array lookup tables with regex in buildUrl (#345) by @usualomanew URL() should be used (#310) by @usualomaRequest object (#311) by @usualomaBlob/ReadableStream cacheable responses (#342) by @usualomaResponse.json() and Response.redirect() spec compliance and efficiency (#343) by @usualomatype: module to package.json (#336) by @yusukebeSo that's v2 of the Node.js adapter — significantly faster, with the same API. Just upgrading should give you a real performance boost. No more "Hono is slow on Node.js" excuses. Please use Hono — fast not only on Cloudflare, Bun, and Deno, but now also on Node.js.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
fix: add custom inspect to lightweight Request/Response to prevent TypeError on console.log by @usualoma in https://github.com/honojs/node-server/pull
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.13...v1.19.14
Fixed an issue in Serve Static Middleware where inconsistent handling of repeated slashes (//) between the router and static file resolution could all
Fixed an issue in Serve Static Middleware where inconsistent handling of repeated slashes (//) between the router and static file resolution could allow middleware to be bypassed. Users of Serve Static Middleware are encouraged to upgrade to this version.
See GHSA-92pp-h63x-v22m for details.
chore: ignore claude setting by @yusukebe in https://github.com/honojs/node-server/pull/314
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.11...v1.19.12
fix: do not overwrite Content-Length in the fast path pattern if Content-Length already exists. by @usualoma in https://github.com/honojs/node-server/
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.10...v1.19.11
Fixed an authorization bypass in Serve Static Middleware caused by inconsistent URL decoding (%2F handling) between the router and static file resolut
Fixed an authorization bypass in Serve Static Middleware caused by inconsistent URL decoding (%2F handling) between the router and static file resolution. Users of Serve Static Middleware are encouraged to upgrade to this version.
See GHSA-wc8c-qw6v-h7f6 for details.
fix(globals): Stop overwriting global.fetch by @usualoma in https://github.com/honojs/node-server/pull/295
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.8...v1.19.9
docs: add guide for listening to UNIX domain socket by @TransparentLC in https://github.com/honojs/node-server/pull/292
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.7...v1.19.8
fix: Fix for hono issue 4563 - incorrect content-length after following symlink by @tshmieldev in https://github.com/honojs/node-server/pull/290
configVersion to bun.lock by @yusukebe in https://github.com/honojs/node-server/pull/291Full Changelog: https://github.com/honojs/node-server/compare/v1.19.6...v1.19.7
fix(serve-static): fix onFound timing by @usualoma in https://github.com/honojs/node-server/pull/286
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.5...v1.19.6
fix: cancel a readable stream if a writable stream is closed before a readable stream is closed. by @usualoma in https://github.com/honojs/node-server
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.4...v1.19.5
fix(serve-static): Add error handling in createStreamBody by @thongdoan in https://github.com/honojs/node-server/pull/278
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.3...v1.19.4
fix: Refactor promise check for response handling by @kay-is in https://github.com/honojs/node-server/pull/277
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.2...v1.19.3
fix: better handle range parse to avoid NaN error by @zwpaper in https://github.com/honojs/node-server/pull/276
Full Changelog: https://github.com/honojs/node-server/compare/v1.19.1...v1.19.2
fix: Keep lightweight request even if accessing method, url or headers by @usualoma in https://github.com/honojs/node-server/pull/274
packageManager field in package.json by @yusukebe in https://github.com/honojs/node-server/pull/275Full Changelog: https://github.com/honojs/node-server/compare/v1.19.0...v1.19.1
feat: add log when directory does not exists by @Its-Just-Nans in https://github.com/honojs/node-server/pull/273
Full Changelog: https://github.com/honojs/node-server/compare/v1.18.2...v1.19.0
fix: Skip content-length assignment when transfer-encoding is chunked. by @usualoma in https://github.com/honojs/node-server/pull/271
Full Changelog: https://github.com/honojs/node-server/compare/v1.18.1...v1.18.2
fix(listener): Limit retries to a maximum of three. by @usualoma in https://github.com/honojs/node-server/pull/267
Full Changelog: https://github.com/honojs/node-server/compare/v1.18.0...v1.18.1
feat: always respond res.body by @usualoma in https://github.com/honojs/node-server/pull/262
res.body by @usualoma in https://github.com/honojs/node-server/pull/262v24 for CI by @yusukebe in https://github.com/honojs/node-server/pull/263Full Changelog: https://github.com/honojs/node-server/compare/v1.17.1...v1.18.0
fix: handle client disconnection without canceling stream by @yusukebe in https://github.com/honojs/node-server/pull/258
Full Changelog: https://github.com/honojs/node-server/compare/v1.17.0...v1.17.1
docs: separate description of autoCleanupIncoming by @usualoma in https://github.com/honojs/node-server/pull/255
server_socket.test.ts to server-socket.test.ts by @yusukebe in https://github.com/honojs/node-server/pull/256Full Changelog: https://github.com/honojs/node-server/compare/v1.16.0...v1.17.0
feat: Clean up the incoming object if the request is not completely finished. by @usualoma in https://github.com/honojs/node-server/pull/252
Full Changelog: https://github.com/honojs/node-server/compare/v1.15.0...v1.16.0
feat(serve-static): pass context to rewriteRequestPath by @yusukebe in https://github.com/honojs/node-server/pull/247
rewriteRequestPath by @yusukebe in https://github.com/honojs/node-server/pull/247Full Changelog: https://github.com/honojs/node-server/compare/v1.14.4...v1.15.0
fix: flush headers before sending data via readable stream by @usualoma in https://github.com/honojs/node-server/pull/245
Full Changelog: https://github.com/honojs/node-server/compare/v1.14.3...v1.14.4
fix: set RequestError name properly by @yusukebe in https://github.com/honojs/node-server/pull/243
RequestError name properly by @yusukebe in https://github.com/honojs/node-server/pull/243Full Changelog: https://github.com/honojs/node-server/compare/v1.14.2...v1.14.3
perf: keep using the lightweight Response object when retrieving headers, status, and ok, and then drop the getInternalBody function. by @usualoma in
headers, status, and ok, and then drop the getInternalBody function. by @usualoma in https://github.com/honojs/node-server/pull/242Full Changelog: https://github.com/honojs/node-server/compare/v1.14.1...v1.14.2
fix: Handle Response Errors Correctly by @jpulec in https://github.com/honojs/node-server/pull/236
Full Changelog: https://github.com/honojs/node-server/compare/v1.14.0...v1.14.1
chore: use Bun as a package manager by @yusukebe in https://github.com/honojs/node-server/pull/224
responseViaCache by @yusukebe in https://github.com/honojs/node-server/pull/234Full Changelog: https://github.com/honojs/node-server/compare/v1.13.8...v1.14.0
fix: export ServerOptions type by @aryasaatvik in https://github.com/honojs/node-server/pull/222
incoming.rawBody if available by @usualoma in https://github.com/honojs/node-server/pull/223Full Changelog: https://github.com/honojs/node-server/compare/v1.13.7...v1.13.8
fix: detection of client premature close by @Tomas2D in https://github.com/honojs/node-server/pull/218
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.6...v1.13.7
fix: conninfo returns server IP by @nakasyou in https://github.com/honojs/node-server/pull/216
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.5...v1.13.6
fix(utils): accept HeadersInit, null, undefined in buildOutgoingHttpHeaders by @usualoma in https://github.com/honojs/node-server/pull/212
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.4...v1.13.5
fix: TypeError: headers is not iterable by @mjad218 in https://github.com/honojs/node-server/pull/210
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.3...v1.13.4
fix(serve-static): add error handler for decoding uri components by @alumowa in https://github.com/honojs/node-server/pull/208
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.2...v1.13.3
fix(serve): support ipv6 by default by @sinasab in https://github.com/honojs/node-server/pull/206
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.1...v1.13.2
fix(serve-static): use application/octet-stream if the mime type is not detected by @usualoma in https://github.com/honojs/node-server/pull/201
Full Changelog: https://github.com/honojs/node-server/compare/v1.13.0...v1.13.1
chore(lint): use eslint v9 by @Jayllyz in https://github.com/honojs/node-server/pull/197
onFound option by @yusukebe in https://github.com/honojs/node-server/pull/198precompressed option by @yusukebe in https://github.com/honojs/node-server/pull/199Full Changelog: https://github.com/honojs/node-server/compare/v1.12.2...v1.13.0
fix: Declare hono as peer dependency by @marvinruder in https://github.com/honojs/node-server/pull/192
hono as peer dependency by @marvinruder in https://github.com/honojs/node-server/pull/192Full Changelog: https://github.com/honojs/node-server/compare/v1.12.1...v1.12.2
fix: return response from res.body if internal data is not ready to be returned directly by @usualoma in https://github.com/honojs/node-server/pull/18
Full Changelog: https://github.com/honojs/node-server/compare/v1.12.0...v1.12.1
fix(serve-static): supports extension less files by @yusukebe in https://github.com/honojs/node-server/pull/183
Full Changelog: https://github.com/honojs/node-server/compare/v1.11.5...v1.12.0
fix: make hono as external to build by @yusukebe in https://github.com/honojs/node-server/pull/182
hono as external to build by @yusukebe in https://github.com/honojs/node-server/pull/182Full Changelog: https://github.com/honojs/node-server/compare/v1.11.4...v1.11.5
Your coding agent can read these notes before it upgrades. Set up the MCP server →