↓この記事の後半のパフォーマンスチェック部分の続き。なんか違和感がある結果だなぁって思ってて、もう少し詳しくみていったら今度はわりと納得できる結果になった。
Validationの違和感
Koriはバリデーターによってパフォーマンスが大きく変わることはないのに、Honoは違っていてValibotのパフォーマンスがいいのが気になっていた。KoriとHonoでそんなに傾向に違いがでるものなのかなぁ?って。

なんでだろう?Koriのバグなのかな?と思って見てみても正しくうごいていそう。と、ふと、Valibotのエンドポイントだけにしてみたら結果が変わった。
元々はこういうふうに1つのappにすべてのエンドポイントを登録して、それぞれのエンドポイントに順番に負荷をかけて結果を見ていた。(このコードはHonoの部分)
app.get('/', (c) => c.text('Hi')) .get('/id/:id', (c) => { c.header('x-powered-by', 'benchmark') return c.text(`${c.req.param('id')} ${c.req.query('name')}`) }) .post('/json', (c) => c.req.json().then((body) => c.json(body))) .post('/validate-zod', sValidator('json', zodSchema), (c) => c.json(c.req.valid('json')) ) .post('/validate-valibot', sValidator('json', valibotSchema), (c) => c.json(c.req.valid('json')) ) .post('/validate-arktype', sValidator('json', arktypeSchema), (c) => c.json(c.req.valid('json')) )
それを1つのエンドポイントだけにして、負荷をかけたら結果が変わったのだ。
const app = new Hono(); app.post( "/", sValidator("json", valibotSchema), (c) => c.json(c.req.valid("json")), );
つまり、複数のエンドポイントを登録してたから、ルーティングがパフォーマンスに影響を与えてたってことか。ということは、バリデーターによるパフォーマンスの違いを見るなら1つのエンドポイントにしてチェックしなきゃだな。
シングルエンドポイントで再チェック
ということで、1つのエンドポイントにして負荷をかけたら、わりと納得できる結果になった。
リポジトリは前回と同じ、ここ
Results (req/s)
| Runtime | Framework | ping | query | body | zod | valibot | arktype | elysia-t |
|---|---|---|---|---|---|---|---|---|
| bun | elysia@1.4.15 | 262,874 | 68,157 | 66,073 | 50,063 | 47,849 | 49,988 | 45,280 |
| deno | hono@4.10.4 | 109,988 | 69,248 | 47,712 | 39,662 | 41,646 | 41,098 | - |
| deno | kori@0.3.4 | 95,314 | 81,964 | 55,168 | 40,720 | 41,061 | 41,706 | - |
| bun | hono@4.10.4 | 85,158 | 63,098 | 50,551 | 43,158 | 42,973 | 42,272 | - |
| bun | kori@0.3.4 | 74,613 | 62,301 | 58,756 | 38,383 | 37,140 | 37,936 | - |
| node | fastify@5.6.1 | 71,663 | 65,422 | 33,421 | - | - | - | - |
| node | hono@4.10.4 | 66,110 | 57,674 | 19,748 | 18,060 | 17,658 | 17,937 | - |
| node | kori@0.3.4 | 60,881 | 55,401 | 22,714 | 18,324 | 18,591 | 19,173 | - |
| node | express@5.1.0 | 14,677 | 14,012 | 11,051 | - | - | - | - |
グラフ

感想
ElysiaのPing(Hiと返すだけのエンドポイント)がめちゃ速い。最初にx64で見てたときは10万rpsを切ってたのだけど、arm64に変更したら26万rps出してきて、へー!全然違うんだなぁ!ってなった。
それ以外の項目もElysiaが速いのは速いけど、Pingほど大きな差ではないなという感想。
バリデーターによって多少の違いはあるものの、そんなに大きな違いはない。前回のHonoはZodよりValibotの方が結構いいパフォーマンスを出していたけど、今回はそこまで変わらない。
Elysiaの組み込みバリデーションの t は速いのかな?と思ってチェックしてみたけど、Elysiaの他のバリデータの方が速かった。
HonoとKoriはBunよりDenoの方がいいパフォーマンスを出してる。特にDeno + Koriのクエリパラメータだけ触るエンドポイントがElysiaを超えてるのは笑った。なんで?
ということで、今回は全体的に納得できる結果になった。
参考
結果はここに出力されている
複数エンドポイントでもチェック
複数エンドポイントを登録してたことがパフォーマンスに影響を与えてたんだよなぁ、じゃあ、複数エンドポイントを登録してる場合は、どういう傾向になるんだろう?と興味がでたので、Zodでバリデーションをかける形で1つのインスタンスに10エンドポイント登録して負荷をかけてみた。これもまぁ納得できるかな。
Endpoints
| # | Method | Path | Validation |
|---|---|---|---|
| ① | GET | /api/users/:id | UUID param |
| ② | GET | /api/users | Query params (page, limit) |
| ③ | POST | /api/users | Body |
| ④ | PUT | /api/users/:id | UUID param + body |
| ⑤ | DELETE | /api/users/:id | UUID param |
| ⑥ | GET | /api/posts/:id | Numeric ID param |
| ⑦ | GET | /api/posts | Query params (userId, page) |
| ⑧ | POST | /api/posts | Body |
| ⑨ | PUT | /api/posts/:id | Numeric ID param + body |
| ⑩ | POST | /api/comments | Body |
Results (req/s)
| Runtime | Framework | Avg | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bun | elysia@1.4.15 | 54,790 | 70,050 | 57,932 | 44,456 | 43,075 | 69,463 | 70,067 | 57,311 | 45,188 | 43,758 | 46,600 |
| deno | kori@0.3.4 | 47,199 | 46,080 | 59,239 | 40,063 | 30,549 | 60,560 | 62,094 | 60,570 | 40,493 | 31,748 | 40,595 |
| deno | hono@4.10.4 | 46,230 | 44,774 | 57,603 | 41,055 | 30,505 | 57,367 | 58,976 | 57,276 | 41,205 | 31,661 | 41,883 |
| bun | hono@4.10.4 | 41,618 | 45,340 | 45,374 | 39,937 | 34,483 | 44,890 | 46,449 | 44,152 | 39,989 | 35,572 | 39,991 |
| node | fastify@5.6.1 | 39,860 | 50,679 | 49,881 | 29,532 | 29,113 | 51,420 | 51,829 | 50,234 | 28,577 | 28,258 | 29,078 |
| bun | kori@0.3.4 | 39,281 | 43,705 | 43,405 | 35,837 | 32,454 | 43,139 | 44,163 | 42,777 | 36,541 | 33,939 | 36,847 |
| node | hono@4.10.4 | 26,003 | 38,991 | 36,905 | 17,803 | 15,780 | 35,951 | 35,000 | 33,150 | 15,684 | 14,774 | 15,988 |
| node | kori@0.3.4 | 21,308 | 27,314 | 25,965 | 17,631 | 16,409 | 22,206 | 26,429 | 25,789 | 17,515 | 16,187 | 17,630 |
グラフ

感想
やっぱり、Elysiaとめちゃくちゃ差があるって感じではないんだなぁという感想
Node.js + Fastifyが、Bun + Hono/Kori より半分のエンドポイントで速いのすごい
やっぱりHonoとKoriはDenoが速い。特にKoriはなぜかDenoと相性がいいみたい
参考
結果はここに出力されている
まとめ
今回の結果にはわりと納得した。KoriがHonoより遅すぎないことを確認したくて始めたチェックだけど、ちょっと遅いくらいで遅すぎはしないなって思えたのでよかった。
あとは、このベンチをローカルで流しながら、フレームグラフでも眺めてちょこちょこチューニングしてみるかな。
おしまい
今日は @kosui_me に「Koriのパフォーマンステストの結果がちょっと違和感あるんだよねー」って雑談してたら「椎葉さん、それはAPMを入れたりしてフレームグラフなどを見ましょう」って言われて「はい、おっしゃるとおりです」ってなったよね。
— mitz (@bufferings) October 29, 2025
おまけ
負荷をかけながら、いろいろ気になったことがあって対応していったら、いろいろやりすぎてしまった。プライベートは好き勝手にできてよい。
- ついでに、Elysiaの
tという組み込みバリデーターもチェックしてみることにした - ついでに、SVGでグラフも生成してもらうことにした
- ぱっと見て分かりたいなと思って「State of JSのこういうグラフみたいなので頼む!」ってお願いした
- ついでに、Load/TargetのVMを分けようと思って、Google Cloud上にSelf Hosted Runner + 1VMを起動して負荷をかけて、終わったらシャットダウンするGitHub Actionsにした
- だから、このリポジトリには僕以外をInviteしてはいけない(GitHub Actions経由でGoogle CloudのVMを操作できてしまうから)
- ついでに、x64じゃなくてarm64のイメージを使うことにした
- Bunはarm64の方がパフォーマンスがいいのかなと思って & 実際にアプリをデプロイするならarm64にするかなぁと思って。結果ElysiaのPingエンドポイントがめちゃ速くなった
- ついでに、bombardierじゃなくてohaを使って負荷をかけることにした
- ohaだと複数エンドポイントに負荷をかけられるから入れ替えてみたけど、結局その機能は使わなかったから、まぁbombardierのままでも良かった。でもohaはおはようだし、なんとなく好き
- ついでに、HonoはRegExpRouterじゃなくてSmartRouterを使うことにした
- これも、僕が使うときはRegExpRouterじゃなくてSmartRouterを使うよなと思ってそうした。遅くなるのかな?と思ったけど今回のテストの範囲では影響は感じなかった
- Google CloudのVMでCPUをいっぱい積んだやつでやってもそんなにパフォーマンスが変わらなくて、よくよく調べてみたらNode.jsもDenoもBunも通常はシングルスレッドで動くんだった。そっか。ということで2コアにしてスッキリした。
- あと、大阪に住んでるから大阪リージョンで構築してたんだけど、そっちにはarm64のマシンが構築できなくて、結局東京リージョンで作り直した。