QUEST LOG · October 10, 2025· UPDATED October 29, 2026

ElysiaJS と Hono のコアな選択、月とスッポン? いいえ、双璧です

serverless でバックエンドを書いている人なら、Hono というフレームワークはきっとよく使っているはず。でも、それが唯一の答えとは限りません。いい匂いのする ElysiaJS も、ぜひ一度味見してみてください。

ちょうど手元で両方とも使っています。Solid(ar)ity のバックエンドは Hono + zod-openapi、このブログの CMS は Elysia で、どちらも Cloudflare Workers 上で動いています。しばらく使ってみて気づいたのは、この 2 つのフレームワークは見た目こそよく似ているものの、コアの取捨選択がまったく違うということ。この記事では benchmark は比べません。比べるのは「それぞれが何を最優先にしているか」です。


# ひとことで言うと

  • Hono:Web 標準ファースト。 コアは Request が入って Response が出るだけなので、Workers、Deno、Bun、Node とどこでも動く
  • Elysia:型ファースト。 コアは schema から handler、フロントエンドの client まで、型を一本につなげること。Bun がホームグラウンド

どちらも速くて小さい。違いは、その優先順位のために何を犠牲にできるか、です。

# Hono:Workers ではネイティブそのもの

Hono を Workers で使っていて一番快適なのは、binding が context に直接乗っていることです。

ts
app.get('/posts', async (c) => {
  const index = await c.env.R2.get('index.json')
  return c.json(await index?.json())
})

c.env はその request の env そのもので、魔法は何もありません。Workers はもともと「binding は request と一緒に動く」という設計で、Hono はちょうどそのモデルどおりに作られているので、プラットフォームとケンカしません。

バリデーションを厳密にしたければ、@hono/zod-openapi を足せば OK。schema を 1 回書くだけで、バリデーションと OpenAPI ドキュメントが一緒に出てきます。Solid(ar)ity のバックエンドは外部から連携してもらう前提なので、自動生成される API ドキュメントがあるのはとても重要で、これが当初 Hono を選んだ理由でもあります。

# Elysia:型がフロントエンドまでつながる

Elysia の売りは end-to-end type safety です。TypeBox で schema を書けば、handler の引数や戻り値、さらにはフロントエンドから Eden で API を呼ぶときの型まで、すべて自動で推論されます。フロントとバックのどちらかを変えると、もう片方が即座に赤線になります。

フロントもバックも自分で書く小さなプロジェクトなら、この体験は本当に気持ちいいです。フルスタック的には最高。このブログの管理画面も、Svelte のフロントエンドが同じ repo の Elysia API を直接叩いていて、フィールドをひとつ変えると、どこが追従できていないかを TypeScript がすぐに教えてくれます。


ただし、Elysia を Workers に載せるには、2 か所で妥協が必要です。

1. AOT をオフにする

Elysia は速さのために、デフォルトで起動時にコードを動的生成します(AOT compile)。でも Workers は new Function / eval のような動的コードを禁止しているので、必ずこうします。

ts
new Elysia({ aot: false })

この 1 行がないと、デプロイした瞬間にエラーになります。AOT をオフにすると、Workers 上の Elysia は Bun 上ほど速くはなくなりますが、管理画面ならまったく体感できません。

2. env は自分で渡す

Elysia には c.env のようなものがありません。私は Worker の fetch エントリで、AsyncLocalStorage を使って env を包んでいます。

ts
export default {
  fetch(request, env) {
    return runWithEnv(env, () => app.handle(request))
  },
}

handler の中では useEnv() で取り出します。これには nodejs_compat を有効にして node:async_hooks を使えるようにする必要があります。動くことは動くのですが、自前で発明したレイヤーが 1 枚増えるわけで、こういう接着剤を書きすぎると、それが将来の技術的負債になります。バックエンドは軽ければ軽いほど、あとでパッチ対応などでアップグレードするときに困ることが少なくて済みます。

# で、どう選ぶ?

私の選び方はシンプルです。

状況選ぶもの
主に Workers / 複数の runtime で動かすHono
API を外部に連携してもらう、OpenAPI ドキュメントが必要Hono + zod-openapi
フロントもバックも自分で書く、同じ repo、主に Bun で動かすElysia
フロントから API を呼ぶときの型をとても重視するElysia + Eden

結局のところ、Hono はプラットフォームに沿って育ったフレームワーク、Elysia は開発体験に沿って育ったフレームワークです。Workers 上ではプラットフォームに沿ったほうが摩擦がずっと少なく、Bun 上では Elysia の型体験はなかなか代わりがききません。

もし今ブログの管理画面を書き直すなら、たぶん Hono を選んで、AOT と AsyncLocalStorage という 2 つの接着剤をなくすと思います。とはいえ、当時 Elysia を選んだことも後悔していません。フロントとバックが一緒に赤線になるあの快感は、小さなツールを書くときには本当にたまらないんですよね。

公開中のアプリ

iOS・Android で無料。

AniSeekr

AniSeekr

MAL・AniList・Bangumi など 6 つのサービスの視聴記録をまとめて、作品の聖地も巡れるアニメ伴走アプリ。

Solid(ar)ity

Solid(ar)ity

プライバシー重視の ID ウォレット。ゼロ知識証明と署名付き名刺を対面で交換、中央サーバーなし。