去年の10月、本番環境でアラートが鳴り続けた。東南アジアのユーザーから「APIが遅すぎて使えない」というクレームが相次ぎ、Slackが荒れていた。
チームは4人。BtoB向けのSaaSダッシュボードを作っていて、サーバーはus-east-1に置いていた。東京でのテストでは問題ない。でも、バンコクやジャカルタのユーザーには600〜800msのAPI応答時間が出ていた。DatadogのP95レイテンシグラフは、日本とASEANで二つの山を描いていた。
エッジコンピューティングの話は前から知っていた。「大企業向けの話だろう」という先入観があって、4人チームには関係ないと思い込んでいた。あの金曜日の午後に本腰を入れて調べ始めて、その後3週間かけていくつかのプラットフォームを試した。
なぜエッジが「遅延の壁」を越えられるのか
原理はシンプルだ。コードをユーザーの近くで動かす。
ただし「近く」の定義が重要で、Cloudflare Workersの場合、2026年2月時点で世界310以上のデータセンターにコードがデプロイされる。バンコクからリクエストが来ると、そのリクエストはバンコク近くのPoP(Point of Presence)で処理される。us-east-1まで往復する必要がない。
これは物理的な距離の問題だから、ソフトウェアの最適化だけでは根本的に解決できない。光の速度は変えられないから。
僕が最初に誤解していたのは「エッジ = CDNでの静的ファイル配信」だと思っていた点だ。確かにそれもエッジの使い方のひとつだけど、今は動的なAPIロジック、認証処理、AIの推論まで、エッジで動かせるようになっている。Cloudflare Workers AI、Fastly Compute、Vercel Edge Functionsあたりが急速に実用レベルに達した時期が、ちょうど2025年後半だったと思う。
一方で制約もある。Cloudflare WorkersはV8アイソレートベースなので、Node.jsのAPIがすべて使えるわけじゃない。fsモジュールは使えないし、実行時間にも上限がある(無料プランは50ms CPUタイム、Paidプランは30秒)。この制約を最初に理解しないと、後で痛い目を見る。
実際に痛い目を見た。
Cloudflare Workers vs Fly.io — 3週間比較した正直な感想
まずCloudflare Workersから試した。
セットアップは思ったより簡単だった。wrangler CLIを入れて、HonoベースのAPIを移植しようとした。Honoはエッジ対応していてWorkers上で動く。問題は、既存コードがNode.js固有のAPIに依存していた部分が散在していたことだ。特にファイルシステムを使ったキャッシュ処理と、cryptoモジュールの一部の使い方。
全部書き直すのに約5日かかった。既存コードの20%くらいが何らかの形で修正が必要だった。
書き直し後のパフォーマンスは印象的だった。バンコクからの平均応答時間が640msから89msに落ちた。3週間の計測平均で7倍以上の改善。体感でわかるレベルの差で、QAチームのメンバーが最初に気づいたくらいだ。
ただ、僕たちのメインDBはRDSだった。エッジからRDSへの接続は、どこかのリージョンを経由するので、DBクエリが多いエンドポイントでは恩恵が半減した。認証チェックや設定値の返却みたいな「DB非依存の処理」では劇的に速くなったけど、複雑なデータ取得エンドポイントでは30〜40%の改善に留まった。
Fly.ioは別のアプローチだ。V8アイソレートじゃなくて、Dockerコンテナをグローバルに分散させる。Node.jsのAPIがそのまま使えるし、既存コードの移植コストが低い。
実際、既存のExpressアプリをFly.ioに乗せるのは2時間で終わった。fly launchして、fly.tomlを少し弄っただけ。バンコクからの平均が640msから180msに改善した。Workersほど低レイテンシじゃないけど、移植コストを考えると、コスパが良い場面が多い。
で、結局どちらを選ぶべきか。僕はこう考えている:
コードの大規模な書き直しなしにグローバル展開したいならFly.io。認証ミドルウェアやAPIゲートウェイみたいな「薄いレイヤー」をエッジに置きたいならCloudflare Workers。既存のDBアーキテクチャを維持したままですべてを速くしようとすると、どちらも限界がある。
コードで見る、エッジデプロイメントの実際
認証処理をエッジで完結させる、というパターンが一番効果的だった。僕たちのケースでは、JWTの検証のためだけにus-east-1まで往復していた。これをWorkers上で処理するように変えた。
// Cloudflare Workers + Hono の構成
// wrangler.toml: compatibility_date = "2025-11-01"
import { Hono } from 'hono'
import { jwt } from 'hono/jwt'
const app = new Hono<{ Bindings: CloudflareBindings }>()
// JWTの検証をエッジで完結させる
// オリジンクラウドサーバー" rel="nofollow sponsored" target="_blank">サーバーへのリクエスト前に認証済みかどうかを確認できる
app.use('/api/*', jwt({ secret: (c) => c.env.JWT_SECRET }))
// KVを使ったエッジキャッシュ
// DB依存のない設定データはここで完結させる
app.get('/api/config/:tenantId', async (c) => {
const tenantId = c.req.param('tenantId')
// Workers KVはグローバルに低レイテンシで読める
const cached = await c.env.TENANT_CONFIG.get(tenantId, { type: 'json' })
if (cached) {
return c.json(cached, 200, { 'X-Cache': 'HIT' })
}
// キャッシュミスのときだけオリジンにフォールバック
// このパターンが鍵: オリジンへのリクエストを最小化する
const res = await fetch(`${c.env.ORIGIN_URL}/internal/config/${tenantId}`, {
headers: {
'X-Worker-Request': '1',
Authorization: c.req.header('Authorization') ?? '',
},
})
const data = await res.json()
// 次回アクセスのためにKVへ書き込む(TTL: 5分)
await c.env.TENANT_CONFIG.put(tenantId, JSON.stringify(data), {
expirationTtl: 300,
})
return c.json(data)
})
export default app
このコードで重要なのは、JWTの検証をエッジで完結させている点だ。認証チェックのためだけにオリジンへ往復していた処理がなくなる。実際に計測すると、認証が必要なエンドポイントの応答時間が平均210ms短縮された。
一つ注意点: c.env.JWT_SECRETはWrangler経由でシークレットとして渡す必要がある。ローカル開発中は.dev.varsファイルに書けば動作確認できるけど、僕はこの仕組みを最初知らなくて30分くらい迷った。公式ドキュメントのどこに書いてあるのかも最初わからなかった(このページを見ていなかった)。
やらかした話と、予想外だった発見
エッジ移行で一番失敗したのは、コールドスタートの問題を完全に無視していたことだ。
Cloudflare WorkersはV8アイソレートなのでコールドスタートが速い。でも一部の処理をFly.ioで動かしていて、トラフィックが少ない時間帯にコンテナが停止していた。深夜2時に「なんか遅い」というSlackが来て確認したら、スケールゼロからの起動が原因だった。Fly.ioの[http_service]設定でmin_machines_running = 1にするだけで解決したけど、これを知るまでに1時間かかったし、ログだけ見ていたら原因特定はもっと遅れていたと思う。
もう一つ予想外だったこと。エッジにロジックを移すと、デバッグが格段に難しくなる。wrangler devでローカル再現はある程度できるけど、特定のPoPだけで起きる問題を追うのは本当につらい。シンガポールのPoPで特定のUser-Agentのリクエストだけが500エラーになるというバグを追うのに2日かかった。Workersのリクエストログを泥臭く掘るしか方法がなかった。
コストについても思い込みがあった。「エッジに移せばクラウドサーバー” rel=”nofollow sponsored” target=”_blank”>サーバーコストが下がる」と思っていたけど実際は違う。Cloudflare WorkersのFreeプランは1日10万リクエストまで無料、それ以上はPaidプラン(月$5)で100万リクエストあたり$0.30の従量課金が加わる。うちは月500万リクエスト程度なので許容範囲だったけど、オリジンサーバーのコストは別途かかる。エッジを挟むことでオリジンへのリクエストが減った分、全体のコストは下がったけど、単純に「エッジの方が安い」という話じゃない。ちゃんと試算してから動いた方がいい。
余談になるけど、Deno Deployも最近かなり良くなっていて、TypeScriptネイティブで使いやすい。ただ、エコシステムの成熟度はまだCloudflare Workersに及ばない。中規模以上のプロダクションで使えるかどうか、正直まだ確信が持てていない。もう少し様子を見ている段階だ。
結局、エッジは誰のためにあるのか
はっきり言う。グローバルにユーザーがいないなら、今すぐエッジに移行する必要はない。
日本国内だけにサービスを提供していて、サーバーも東京リージョンにあるなら、エッジ化のコスト(コードの書き直し、デバッグの複雑化、アーキテクチャの学習コスト)は見合わないことが多い。僕が3週間かけて移行した価値があったのは、アジア太平洋全域にユーザーがいて、レイテンシの問題がリアルに存在していたからだ。
具体的に言うと、アジア太平洋やグローバルにユーザーが散らばっていて、認証処理やAPIゲートウェイがレイテンシのボトルネックになっているなら、移行を試す価値は十分ある。コードがNode.js固有のAPIに深く依存していないなら、移行コストも思ったより低く収まるはずだ。逆に、複雑なバックエンドロジックをそのままエッジに全部移そうとするのは泥沼になる可能性が高い。
今から始めるなら、まずFly.ioで既存コードをそのままグローバル展開してみる。移植コストが低いので実態を把握しやすい。それで十分かもしれないし、「この部分だけはCloudflare Workersの方が効果的」という具体的な判断ができるようになる。いきなり全部書き直すのではなく、遅延の境界線を見つけながら段階的に移行するのが、現実的なやり方だと思う。