なぜスタックをエッジに移行したのか
私は10年近く、Node.jsとExpressでAPIを構築してきました。それは業界標準であり、長年安定して動作していました。しかし、ユーザーベースがグローバルに広がるにつれ、中央集権的なサーバーの限界を無視できなくなりました。レイテンシはコンバージョン率の「静かなる殺人者」です。シンガポールのユーザーがUS-East-1のサーバーにアクセスすると、最初の1バイトが届くまでに200msから300msの遅延が発生します。このラグは体感できるほど大きなものです。
6ヶ月前、私は3つの高トラフィックなマイクロサービスをHono.jsを使用してCloudflare Workersに移行しました。これは単なるフレームワークの入れ替えではなく、インフラストラクチャの完全な再考でした。APIは単一のデータセンターで待機するのではなく、Cloudflareেরグローバルネットワーク上に存在することになります。エンドユーザーからわずか数キロ先のエッジで実行されるのです。本番運用から半年が経過し、結果は明らかです。レスポンスタイムは激減し、インフラのオーバーヘッドはほぼ消失しました。
比較:Express vs. Hono.js
Expressを知っているなら、Hono.jsは馴染みやすく感じるでしょう。ただし、2010年代のような肥大化はありません。ExpressはNode.jsランタイム用に構築されており、歴史的な重みを抱えています。一方、Cloudflare Workersは、Chromeブラウザ内部と同じ高速なテクノロジーであるV8 isolateエンジンで動作します。この環境はNode.jsの標準ライブラリを完全にはサポートしていないため、最新のWeb標準(Web Standards)に合わせて構築されたフレームワークが必要です。
- ランタイムのオーバーヘッド: 一般的なExpressコンテナは、アイドル状態でも200MBのRAMを消費することがあります。対してHonoは超軽量で、14KB未満に収まります。完全にFetch APIに基づいて構築されているため、モダンなWebに対してネイティブな感覚で動作します。
- 開発者体験(DX): Expressは古いコールバックパターンに依存していますが、HonoはTypeScriptを第一級市民として扱います。特別な設定なしで、ルートや変数に対して完璧なIDE의自動補完が得られます。
- ルーティング速度: HonoはRegexpRouterを使用しています。古いフレームワークが採用している線形探索とは異なり、Honoは定数時間でルートをマッチングします。何百ものエンドポイントがあっても、ルーティングのオーバーヘッドは無視できるほど小さいままです。
本番運用6ヶ月の現実
得られたメリット
最大のメリットは、「コールドスタートの消滅」でした。AWS Lambdaでは、一定期間アクセスがないと関数の「起動」に2秒ほどかかることがあります。Cloudflare Workersは5ミリ秒未満で起動します。ユーザーにとって、APIは瞬時に反応するように感じられます。
コスト効率も驚異的でした。月額120ドルの仮想マシンクラスターを、月額5ドルのCloudflare Workersプランに置き換えることができました。アイドル状態のCPUサイクルではなく、実際の実行時間に対してのみ支払うため、インフラ費用は約75%削減されました。スタートアップにとって、これは再確保された膨大な滑走路(ランウェイ)となります。
ベンダーの柔軟性が3つ目の大きな利点です。Honoは標準のWeb API(Request/Response)に準拠しているため、コードが特定のプラットフォームに依存しません。明日、このAPIをDenoやBun、あるいは標準のNode.jsサーバーに移行したくなっても、最小限のリファクタリングで済みます。特定のクラウドプロバイダーのSDKにロックインされることはもうありません。
課題
良いことばかりではありませんでした。V8 isolate環境の標準プランには**厳格な128MBのメモリ制限**があります。重い画像処理や巨大なCSVファイルのメモリ上での操作が必要な場合、壁にぶつかるでしょう。また、C++アドオンやローカルファイルシステムに依存するNode.jsライブラリも使用できません。デプロイ前に、すべての依存関係が「Worker互換」であることを確認する必要があります。
推奨する本番環境の構成
すべてを1つのファイルに詰め込まないでください。保守性の高いAPIにするには、スケールしてもクリーンな状態を保てる構造が必要です。チーム開発において最も効果的だったレイアウトを紹介します。
project-root/
├── src/
│ ├── index.ts # メインのエントリーポイント
│ ├── routes/ # 機能ベースのルーティング(users, postsなど)
│ ├── middleware/ # 認証、カスタムログ、CORS
│ └── db/ # D1またはKVデータベースのバインディング
├── wrangler.toml # 環境変数と設定ファイル
├── package.json
└── tsconfig.json
CloudflareのCLIであるWranglerの使用を強くお勧めします。エッジ環境をローカルでシミュレートできるため、従来のサーバーレス開発を悩ませていた「自分のマシンでは動く」というバグを事実上排除できます。
クイックスタート:ゼロからエッジへ
セットアップは迅速です。約30秒で本番対応の雛形を作成できます。まずはHonoのイニシャライザを実行します。
npm create hono@latest my-api
プロンプトが表示されたら `cloudflare-workers` を選択します。以下は、必須のミドルウェアとクリーンなルーティングを含む、標準的な `index.ts` の構成例です。
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
const app = new Hono()
// グローバルミドルウェア
app.use('*', logger())
app.use('/api/*', cors())
// シンプルなヘルスチェック
app.get('/', (c) => c.json({ status: 'オンライン', location: 'エッジ' }))
// ダイナミックルート
app.get('/api/user/:id', (c) => {
const id = c.req.param('id')
return c.json({
userId: id,
timestamp: Date.now()
})
})
export default app
データへの接続
高速なAPIには高速なデータが必要です。CloudflareはSQLiteベースのサーバーレスSQLデータベースであるD1を提供しています。Hono内でのアクセスは非常に簡単で、定型的な接続ロジック(ボイラープレート)は一切不要です。
app.get('/api/posts', async (c) => {
// 環境変数からDBバインディングにアクセス
const { results } = await c.env.DB.prepare(
'SELECT id, title FROM posts LIMIT 5'
).all()
return c.json(results)
})
30秒でのデプロイ
デプロイはこのワークフローの最高の瞬間です。認証が済んだら、以下を実行するだけです。
npm run deploy
コードは最適化・バンドルされ、世界中の300以上のデータセンターにプッシュされます。これにかかる時間は30秒未満です。このスピードはチームの働き方を変えました。大規模でリスクの高い週1回のリリースではなく、小さく段階的なアップデートを1日に何度も行えるようになったのです。
最終的な結論
Cloudflare Workers上のHono.jsに切り替えたことで、仕事の中でも特に退屈な部分がなくなりました。週末にLinuxカーネルのパッチを当てたり、オートスケーリンググループの設定に悩んだりする必要はもうありません。インフラは、10件のリクエストを捌くのと同じくらい簡単に、数百万のリクエストを処理してくれます。新しいプロジェクトを始めるなら、従来のExpressスタックの先を見てください。ユーザーが得られるパフォーマンスの向上と、開発者が得られる心の平穏は、見逃すにはあまりにも惜しいものです。

