AWS Lambda vs Cloudflare Workers – 異なる設計思想のサーバーレスアーキテクチャ
はじめに
サーバーレスアーキテクチャはコードをデプロイするだけでアプリケーションを動かすことのできるプラットフォームであり、その中でも関数単位でコードを実行するサービスは Function as a Service (FaaS) とも呼ばれています。 このサービスの代表格としては AWS の Lambda、 GCP の Cloud Functions、 Microsoft Azure の Azure Functions、 そして Cloudflare の Cloudflare Workers が挙げられます。 これらのサービスはどれも「サーバーを管理せずにコードを実行できる」という点では共通していますが、実際に調べてみると前者の3つと、Cloudflare Workers は基本的なアーキテクチャがかなり違います。
筆者自身、最初は AWS Lambda の延長線上で Cloudflare Workers を理解しようとしましたが、サービスを調べていくと、これらは同じサービスではないと気づきました。 これらは同じ「サーバーレス」という括りで語られることが多いですが、動作モデルが根本的に違います。
本記事では、AWS Lambda と Cloudflare Workers の違いをいくつかの観点から整理します。
動かす場所の違い
AWS Lambda:リージョン中心のコンピューティング
AWS Lambda は、指定したリージョン(例:ap-northeast-1)でコードを実行します。Lambda 自体は CloudFront のオリジンとしても設定することができる通り、処理自体は特定のリージョンで行われます。
Cloudflare Workers:エッジネイティブ
Cloudflare Workers は最初からエッジロケーションで動作するように設計されています。Cloudflare の CDN ネットワーク上のノードでコードが実行されるため、ユーザーに最も近い場所で処理が完結します。
Lambda@Edge / CloudFront Functions:AWSでのエッジコンピューティング
Cloudflare Workers はエッジ上でのサーバーレス実行環境なので、AWS で比較するのであれば同じ「エッジで動かす」サービス、すなわち、Lambda@Edge や CloudFront Functions が実際の比較対象となります。 しかし、これらのエッジコンピューティングに関しては、AWS では非常に強い制約(利用可能リソースのレイテンシなど、後述)がありますので、補助的利用以外では基本的には AWS Lambda をオリジンとする設計を選択することが多くなるかと思います。
サーバーレス実行環境としてまとめると、AWS Lambda は CDN エッジ外に多くの計算資源を持っているため、それを活用するアプローチを基本としていますように見えます。 一方、Cloudflare は CDN がメインの計算資源であるためか、エッジノードで更なる活用が可能となるアプローチを取っています。
この違いが、以降のキャッシュやデータアクセスの設計にも影響してきます。
リクエスト課金とキャッシュの関係
AWS Lambda(+ CloudFront):キャッシュヒットすれば Lambda は動かない
基本的な AWS の構成では、CloudFront がキャッシュを管理し、Lambda をそのオリジンとして動作させます。 この場合、リクエストが CloudFront のキャッシュにヒットすれば、オリジン側の Lambda は呼び出されません。つまり、CDN キャッシュを活用することで、オリジンの呼び出し回数を抑えることができ、その分 Lambda の課金を抑えることができます。これは、通常の AWS Lambda がオリジン型の設計をされていることを考えると、自然な動作です。
Lambda@Edge の場合はもう少し複雑で、CloudFront のイベントタイプによって挙動が変わります。Viewer Request / Viewer Response はキャッシュの前後で毎回実行されますが、Origin Request / Origin Response はキャッシュミス時のみ実行されます。
Cloudflare Workers:キャッシュヒットしても Workers は動く
Cloudflare Workers の動作モデルはこれと根本的に異なります。Workers が実行されるパスに対してリクエストがあった場合、キャッシュの有無に寄らず Worker は必ず実行されます。 Lambda@Edge で例えると、Cloudflare Workers は「Viewer Request / Response」をまとめて実行するような役割になります。
では Workers の挙動はキャッシュの有無とどう関係するのでしょうか?
答えは Workers は Cache API を通じて、自らキャッシュの読み書きを制御します。つまり、Workers にとってキャッシュとは「外側」にあるものではなく「自分で操作する」ものなのです。
// Workers 内での Cache API の利用イメージ
async function handleRequest(request) {
const cache = caches.default;
let response = await cache.match(request);
if (!response) {
// キャッシュミス:オリジンから取得してキャッシュに格納
response = await fetch(request);
const responseToCache = response.clone();
await cache.put(request, responseToCache);
}
return response;
}
この違いは関数実行の課金モデルに直結します。
AWSでは CloudFront のアクセス数・データアウトプット容量に加え、Lambda 関数の実行時間が課金対象です。そして、これらのレイヤーが分離されているため、CloudFront でキャッシュヒットすれば、Lambda は呼び出されないという特徴があります。
一方、Cloudflare Workers は CDN 一体型という性質があるため、リクエスト・関数の実行時間それぞれで課金が発生します。 そのため、キャッシュヒット時もコストが発生します。ただし、キャッシュの制御ロジックをアプリケーションコード内で柔軟に記述できるという利点があります。
| AWS (Lambda + CloudFront) | Cloudflare Workers | |
|---|---|---|
| キャッシュヒット時の挙動 | Origin に設定した Lambda は呼び出されない ※Lambda@Edge は設定次第で実行される |
Workers は毎回実行される |
| キャッシュの制御 | CloudFront の設定で管理 | Workers 内の Cache API で制御 |
| 関数呼び出し課金の発生 | キャッシュミス時のみ | 毎リクエスト |
エッジ動作 vs オリジン動作 — データアクセスの壁
エッジでコードを動かせたとしても、データがエッジになければレイテンシの問題は解決しません。ここにも両者の設計思想の違いが現れています。
AWS:エッジにデータを持ってくるのが難しい
Lambda@Edge からアプリケーションデータにアクセスする場合、基本的には S3 や DynamoDB を使うことになります。しかし、これらのリソースは特定のリージョンを指定して作成するため、Lambda@Edge が別リージョンで実行されると、リージョン間のネットワークレイテンシが発生します。
例えば、us-east-1 に DynamoDB を配置し、us-west-2 で Lambda@Edge が実行された場合、各 DB リクエストでリージョン間レイテンシが発生します。エッジでコードを実行してユーザーとの距離を縮めても、データとの距離が遠ければレスポンスが遅延してしまいます。
この問題に対する AWS の解決策は DynamoDB Global Tables です。複数リージョンにテーブルのレプリカを配置し、Lambda@Edge が実行リージョンを検知して最寄りのレプリカにアクセスします。しかし、これにはいくつかの課題があります。
- レプリカリージョンの選定と設定を自分で行う必要がある
- レプリケーションコストが書き込みリクエストユニット × レプリカ数で増加する
- Lambda@Edge 側で AWS_REGION 環境変数を参照して最寄りレプリカにルーティングするコードを自前で実装する必要がある
- レプリカ間は結果整合性であり、レプリカラグを考慮した設計が求められる
より軽量なデータであれば CloudFront KeyValueStore という選択肢もあります。2023年末に登場したこのサービスは、CloudFront Functions からエッジで低レイテンシに読み取りできるグローバルな KV ストアです。ただし、最大サイズ 5MB、値は 1KB までという制約があり、A/B テストのフラグやリダイレクトルールなど、設定データ程度の用途に限られます。
AWSのエッジコンピューティングサービスとして もう一つ、CloudFront Functions がありますが、こちらはそもそも実行時間に強い制約があり、CloudFront KeyValueStore などの例外を除いて他のAWSサービスにアクセスすらできません。
つまり AWS のエッジにおけるデータアクセスは、「リージョンを増やしてデータを近づける」か「ごく小さなデータだけエッジに置く」かの二択であり、エッジでまとまったデータを扱うことはあまり想定されていません。
Cloudflare:エッジでデータを完結させる
AWS とは対称的に、Cloudflare ではエッジでアプリケーションが必要とするデータストアサービスが取り揃えられています。
- Workers KV — グローバルに分散された KV ストア。結果整合性ですが、読み取りはエッジから低レイテンシで行えます
- D1 — SQLite ベースのリレーショナルデータベース。リードレプリカがサポートされている全リージョンに自動的に作成され、開発者がレプリカの配置や管理を行う必要がありません
- R2 — S3 互換のオブジェクトストレージ
特に D1 のリードレプリケーションは注目に値します。有効にすると、Cloudflare が必要に応じて各エッジにリードレプリカを作成し、読み取りクエリを最寄りのレプリカにルーティングします。追加のストレージコストやコンピュートコストは発生しません。
DynamoDB Global Tables と比較すると、D1 のリードレプリケーションはレプリカの配置・ルーティング・コスト管理のすべてが自動化されている点で、エッジでのデータアクセスに対するアプローチが根本的に異なることがわかります。
| AWS (Lambda@Edge + DynamoDB) | Cloudflare (Workers + D1) | |
|---|---|---|
| レプリカの配置 | 手動でリージョンを選定 | 全エッジロケーションに自動作成 |
| ルーティング | 自前でコード実装が必要 | 自動ルーティング |
| 追加コスト | 書き込み × レプリカ数 | 追加コストなし |
まとめ
AWS Lambda と Cloudflare Workers の違いは、単なる機能差ではなく設計思想の違いです。
AWS は「リージョン中心」の設計であり、エッジはあくまで軽量な処理を行う場所として位置づけられていると考えられます。本格的な計算処理やデータ処理はリージョンに寄せます。エッジに持てるデータは CloudFront KeyValueStore の 5MB が上限で、それ以上のデータが必要ならリージョンの DynamoDB Global Tables を使って「リージョンを増やす」ことで対応しますが、コスト面・データ連携遅延などの問題に別途対処する必要があります。
Cloudflare は「エッジ完結」の設計であり、計算処理やデータ処理もエッジ内で完結させることを目指しています。 Workers + データサービスという組み合わせで、アプリケーションに必要なスタックをエッジに揃えており、それを複雑な設定なしで自動的にマルチリージョン対応してくれることがメリットです。
どちらが優れているという話ではありませんが、
- グローバルに分散したユーザーへの低レイテンシ配信が最優先で、読み取り中心のワークロードであれば、Cloudflare のエッジ完結モデルが強い
- AWS の豊富なマネージドサービスや、既存の業務システムなどと連携した複雑なバックエンド処理が必要なら、AWS のリージョンモデルを利用した設計の方が適している
- AWSを使ったとしても、エッジでの処理がヘッダ操作やリダイレクト程度であれば、CloudFront Functions + KeyValueStore で十分なケースも多い
重要なのは、「同じサーバーレスだから同じように使える」と思い込まないことです。 これらの違いを理解することで、どのアーキテクチャを選ぶべきかも変わってきます。


















