Serverless (Lambda/Fargate) vs Edge (Cloudflare):処理特性に応じたリソースの使い分け
Lambda・Fargate・Cloudflare Workersそれぞれの処理特性(レイテンシ・コスト・コールドスタート・制約)を整理し、ユースケース別の最適な選択基準を解説。
はじめに:「とりあえず Lambda」が設計負債になる理由
クラウドで何かを動かすとき、多くのプロジェクトは「サーバーレスなら Lambda」「コンテナなら Fargate」「静的サイトなら Cloudflare」という経験則で選択する。これ自体が間違いではないが、根拠のない経験則は、要件が変わったときに覆せない設計上の固定観念になる。
例えば、こういうケースだ。
よくある設計の歪み:
ケース①: 「全 API を Lambda にした」
→ 一部エンドポイントのレスポンスが 500ms を超える
→ 原因: コールドスタート(VPC Lambda は最大2〜3秒)
→ 対応: Provisioned Concurrency を足す → 月額 $200 増
ケース②: 「画像変換を Workers に入れた」
→ CPU 制限(50ms)に当たり処理が途中で打ち切られる
→ 原因: Workers は長時間 CPU 処理に向かない
→ 対応: Lambda に移し直す → 無駄な移行コスト
ケース③: 「全部 Fargate にしておけば安心」
→ 月の AWS 請求が $500 を超える
→ 原因: 常時起動コンテナ × 24時間 × 低トラフィック
→ 対応: リクエスト駆動のサービスは Lambda/Workers に移す
この記事では、Lambda・Fargate・Cloudflare Workers の処理特性を5軸で定量的に整理し、「どのユースケースにどれが最適か」という判断基準を明文化する。
Part 1:3つの実行モデルの本質的な違い
選択基準を議論する前に、3つのサービスが何を抽象化しているかを理解する必要がある。
実行モデルの違い:
┌──────────────────────────────────────────────────────┐
│ Lambda(AWS) │
│ ┌──────────────────────────────────────────────┐ │
│ │ リクエスト │ │
│ │ → コンテナ起動(コールドスタート or 再利用) │ │
│ │ → ランタイム初期化(Node.js / Python / JVM...) │ │
│ │ → ハンドラ関数実行 │ │
│ │ → レスポンス返却 → コンテナ待機(最大15分) │ │
│ └──────────────────────────────────────────────┘ │
│ 抽象化: OS・ランタイム・スケール。コンテナ単位で課金。 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Fargate(AWS ECS/EKS) │
│ ┌──────────────────────────────────────────────┐ │
│ │ コンテナイメージ(常時起動 or オンデマンド) │ │
│ │ → タスク定義のリソース(CPU・メモリ)で動作 │ │
│ │ → 任意のプロセスが長時間実行可能 │ │
│ │ → 複数リクエストを1コンテナで並行処理 │ │
│ └──────────────────────────────────────────────┘ │
│ 抽象化: EC2インスタンス管理。vCPU・GB単位で課金。 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Cloudflare Workers(V8 Isolate) │
│ ┌──────────────────────────────────────────────┐ │
│ │ リクエスト │ │
│ │ → V8 Isolate(事前ウォーム済み)で即時実行 │ │
│ │ → Web API のみ使用可能(Node.js API 不可) │ │
│ │ → 300+ PoP で並列実行(ユーザー最寄りで動く) │ │
│ │ → CPU 50ms 上限、メモリ 128MB 上限 │ │
│ └──────────────────────────────────────────────┘ │
│ 抽象化: サーバー・OS・リージョン選択。リクエスト単位課金。 │
└──────────────────────────────────────────────────────┘
この3つはそれぞれ異なるレイヤーを抽象化している。比較するときは「どのレイヤーの問題を解決したいか」という視点が重要だ。
Part 2:5軸での定量比較
軸①:コールドスタートレイテンシ
コールドスタートの実態(2025年計測参考値):
Lambda(Node.js、VPC なし):
初回起動: 100〜400ms
ウォーム: 1〜5ms(ランタイム初期化のみ)
Lambda(Node.js、VPC あり):
初回起動: 500ms〜3,000ms(ENIアタッチのオーバーヘッド)
ウォーム: 1〜5ms
※ RDS や ElastiCache アクセスで VPC Lambda になりがち
Fargate(ECS サービス):
タスク起動: 30〜60秒(常時起動なら 0ms)
※ 常時最低1タスク起動で回避するのが一般的
Cloudflare Workers:
コールドスタート: 0ms
※ V8 Isolate はリクエスト前から準備済み
※ ただし D1/KV クエリのレイテンシは別途発生(1〜10ms)
判断基準: P99 レスポンスタイムに SLA がある API → Workers 優位。バッチ処理・非同期ジョブ → コールドスタートは無関係。
軸②:実行時間とリソース上限
実行時間・リソースの上限:
Lambda:
最大実行時間: 15分
メモリ: 128MB〜10,240MB(CPUはメモリに比例)
タイムアウト: 設定値(デフォルト3秒、最大15分)
同時実行: デフォルト1,000(リージョン合算、申請で引上可)
Fargate:
実行時間: 制限なし(常駐プロセス)
CPU: 0.25vCPU〜16vCPU
メモリ: 0.5GB〜120GB
同時実行: コンテナのスペックと台数に依存
Cloudflare Workers:
最大 CPU 時間: 50ms(Free)/ 30秒(Paid)
メモリ: 128MB(拡張不可)
実行時間: 30秒(Paid、待機含む)
※ CPU 50ms はループ処理や暗号計算で超えやすい
判断基準: 処理が CPU バウンドか I/O バウンドかで選択が変わる。
軸③:コスト構造
コスト比較(月100万リクエスト、平均100ms実行):
Lambda(128MB):
リクエスト: $0.20 / 100万
実行時間: $0.0000166667 / GB秒
→ 0.128GB × 0.1秒 × 100万 = 12,800 GB秒
→ $0.0000166667 × 12,800 = $0.21
合計: ≈ $0.41 / 月
Fargate(常時起動 0.25vCPU / 0.5GB × 1タスク):
vCPU: $0.04048 / vCPU時間 × 0.25 × 720h = $7.29
メモリ: $0.004445 / GB時間 × 0.5 × 720h = $1.60
合計: ≈ $8.89 / 月(トラフィックに関係なく固定)
Cloudflare Workers:
月1,000万リクエストまで無料(Free プラン)
Paid: $5/月 + $0.15 / 100万リクエスト
合計: ≈ $5.15 / 月(1,000万超のみ追加課金)
重要な構造的差異:
- Lambda はリクエスト従量課金(使わなければゼロ)
- Fargate はリソース占有課金(起動している限り課金)
- Workers はリクエスト従量課金(無料枠が非常に大きい)
軸④:ランタイム・ライブラリの制約
使えるもの・使えないものの整理:
Lambda:
✅ Node.js / Python / Java / Go / Ruby / .NET
✅ npm パッケージ(ほぼすべて)
✅ fs, child_process, net など Node.js API
✅ バンドルサイズ: 250MB(解凍後)まで
✅ カスタムコンテナイメージ(10GB まで)
Fargate:
✅ 任意の言語・フレームワーク(コンテナで実行)
✅ OS レベルのツール(ffmpeg, ImageMagick 等)
✅ 長時間接続(WebSocket, gRPC streaming)
✅ ファイルシステムへの書き込み
Cloudflare Workers:
✅ TypeScript / JavaScript(V8 ベース)
✅ Web Crypto API, Fetch API, Cache API
✅ npm パッケージ(Web API のみ使うもの)
❌ Node.js API(fs, path, crypto, child_process...)
❌ Node.js 専用 npm パッケージ
⚠️ バンドルサイズ: 10MB まで(圧縮後)
判断基準: 使いたいライブラリが Node.js 依存の場合 → Lambda/Fargate。Web 標準 API で完結する場合 → Workers が候補に入る。
軸⑤:運用・デプロイの複雑さ
運用コスト比較:
Lambda:
デプロイ: zip アップロード or コンテナイメージ push
インフラ: API Gateway, IAM Role, VPC(必要時)の設定
監視: CloudWatch Logs(自動)
スケール: 自動(同時実行上限の管理は必要)
難所: VPC Lambda の冷起動・ENI 枯渇、デプロイパッケージサイズ
Fargate:
デプロイ: ECR に push → ECS サービス更新
インフラ: ECS クラスター, タスク定義, ALB, Security Group...
監視: CloudWatch Container Insights(追加設定要)
スケール: Auto Scaling(設定が必要)
難所: ECS の設定量が多い。IAM/Security Group が複雑化しやすい
Cloudflare Workers:
デプロイ: wrangler deploy(1コマンド)
インフラ: wrangler.jsonc のみ(VPC, SG, ALB 設定不要)
監視: Workers Analytics(ダッシュボードで即確認)
スケール: 全自動(PoP ごとにスケール、設定不要)
難所: Web API 制約への適応、D1/KV 設計
Part 3:ユースケース別の選択マトリクス
5軸の整理をもとに、代表的なユースケースに対する選択基準を示す。
| ユースケース | 推奨 | 理由 |
|---|---|---|
| グローバル配信 API(低レイテンシ必須) | Workers | 300+ PoP、コールドスタート 0ms |
| コンテンツ配信・静的 API(読み取り多) | Workers + D1 | 無料枠、エッジ DB、運用シンプル |
| 非同期バッチ処理(S3 トリガー等) | Lambda | イベント駆動、15分実行、コスト効率 |
| 画像・動画変換(ffmpeg 等) | Lambda/Fargate | OS レベルのツールが使える |
| 長時間実行 Web サーバー(WebSocket 等) | Fargate | 常時起動、持続的接続、任意フレームワーク |
| ML モデル推論(Python / 重い処理) | Lambda/Fargate | Python ランタイム、メモリ上限が高い |
| 認証・認可レイヤー(JWT 検証等) | Workers | 全リクエストに低レイテンシで割り込める |
| スケジュールジョブ(日次バッチ等) | Lambda | EventBridge との統合が容易 |
| 高トラフィック常時稼働 API | Fargate | コンテナ常駐でコールドスタートなし、リクエスト量が増えても単価不変 |
Part 4:ハイブリッド設計パターン
実務では「どれか1つを選ぶ」のではなく、処理特性ごとに最適なサービスを組み合わせるのが現実的だ。
パターン①:Workers をフロントエンドに置くハイブリッド
リクエストフロー:
ユーザー
│
▼
Cloudflare Workers(エッジ)
├─ 認証トークン検証(Web Crypto API で JWT 検証)
├─ レートリミット(KV でカウント)
├─ キャッシュヒット → 即レスポンス
└─ キャッシュミス
│
▼
AWS Lambda(オリジン)
├─ DB クエリ(RDS / DynamoDB)
├─ 複雑なビジネスロジック
└─ Node.js 専用ライブラリの処理
Workers が認証・キャッシュ・レートリミットを肩代わりすることで、Lambda へのリクエスト数が激減する。結果として Lambda のコールドスタート頻度も下がる。
// Workers でのフロント処理例
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// ① JWT 検証(エッジで完結、Lambda に到達する前に弾く)
const token = request.headers.get('Authorization')?.slice(7)
if (!token) return new Response('Unauthorized', { status: 401 })
try {
// Web Crypto API で RS256 検証(Node.js crypto 不要)
await verifyJwt(token, env.JWT_PUBLIC_KEY)
} catch {
return new Response('Invalid token', { status: 401 })
}
// ② Cloudflare Cache でキャッシュ確認
const cacheKey = new Request(request.url)
const cached = await caches.default.match(cacheKey)
if (cached) return cached // キャッシュヒット → Lambda に到達しない
// ③ オリジン(Lambda)へプロキシ
const response = await fetch(env.ORIGIN_URL, request)
// ④ 成功レスポンスをキャッシュに保存
if (response.ok) {
const toCache = response.clone()
caches.default.put(cacheKey, toCache) // 非同期で保存
}
return response
}
}
パターン②:処理特性で Lambda と Fargate を分ける
同一サービスの中でのリソース分割:
┌─────────────────────────────────────────────┐
│ Web API サービス(LP + 連絡フォーム) │
│ │
│ /api/contact → Lambda │
│ 理由: 低頻度・短命・SES 送信のみ │
│ コスト: ほぼ $0(月数十〜数百リクエスト) │
│ │
│ /api/upload → Lambda(コンテナイメージ) │
│ 理由: ffmpeg で画像リサイズ、S3 保存 │
│ コスト: リクエスト単位課金 │
│ │
│ /admin/* → Fargate(常時 1 タスク) │
│ 理由: CMS、セッション管理、長時間プロセス │
│ コスト: $8〜15/月(固定) │
└─────────────────────────────────────────────┘
Part 5:選択を誤りやすいパターンと対策
落とし穴①:VPC Lambda のコールドスタート
Lambda を VPC に入れると、ENI(Elastic Network Interface)のアタッチに時間がかかる。低トラフィック環境では「数秒のコールドスタートが毎リクエスト発生」する状況に陥りやすい。
対策の選択肢:
1. Provisioned Concurrency(ウォーム維持)
→ 月額固定コスト増加(0.25vCPU相当を確保)
→ 開発環境では不要、本番のみで使う
2. VPC Lambda をやめる
→ RDS Proxy 経由で VPC 外から RDS に接続
→ DynamoDB に変更(VPC 不要)
→ DB を D1 / PlanetScale 等に移す
3. Fargate(常時起動)に変更
→ コールドスタートを構造的に排除
落とし穴②:Workers の CPU 50ms 制限
// ❌ Workers でやってはいけないパターン
app.post('/api/hash-passwords', async (c) => {
const { passwords } = await c.req.json()
// bcrypt は CPU を大量消費する → 50ms で打ち切られる
const hashed = await Promise.all(
passwords.map((p: string) => bcrypt.hash(p, 12))
)
return c.json(hashed)
})
// ✅ 正しいアプローチ
// CPU 集約処理は Lambda に分離する
// Workers は Lambda へのプロキシとして機能させる
app.post('/api/hash-passwords', async (c) => {
const body = await c.req.text()
// Lambda の URL Function or API Gateway へ転送
const result = await fetch('https://xxx.lambda-url.ap-northeast-1.on.aws', {
method: 'POST',
body,
headers: { 'Content-Type': 'application/json' },
})
return result
})
落とし穴③:Fargate を「汎用サーバー」として使いすぎる
Fargate の常時起動コストは「トラフィックがゼロでも発生する」。
低トラフィック環境(月10万リク以下)での比較:
Lambda: ほぼ $0(無料枠内)
Fargate: $8〜15/月(常時1タスク)
適切な使い分けのシグナル:
→ リクエスト数が月1,000万を超えてきたら Fargate を検討
→ 常時 WebSocket 接続が必要なら最初から Fargate
→ 月に数回しか動かないジョブ → Lambda 一択
Part 6:意思決定フローチャート
技術選定を判断するときの実務的な手順を整理する。
意思決定フロー:
START
│
▼
長時間実行(15分以上)または常時接続(WebSocket)が必要?
│
Yes → Fargate(常時起動タスク)
│
No
▼
Node.js 固有ライブラリ or OS ツール(ffmpeg 等)が必要?
│
Yes → Lambda or Fargate(コンテナイメージ)
│
No
▼
CPU 集約処理(暗号計算、画像変換、ML 推論)が必要?
│
Yes → Lambda(メモリ・CPU スペックを選べる)
│
No
▼
グローバル低レイテンシ(P99 < 50ms)が要件?
│
Yes → Cloudflare Workers(Edge Runtime)
│
No
▼
月リクエスト数は 1,000 万以下?
│
Yes → Cloudflare Workers Free Tier($0)
│
No
▼
Workers の制約(CPU 50ms、128MB、Web API のみ)で実装可能?
│
Yes → Cloudflare Workers Paid($5/月 +従量)
│
No → Lambda(リクエスト従量課金)
Conclusion:選択基準の言語化が設計力の指標
技術の選択は「どれが優れているか」ではなく「この処理特性には何が最適か」という問いへの回答だ。
| Lambda | Fargate | Cloudflare Workers | |
|---|---|---|---|
| コールドスタート | △ 100ms〜数秒 | ✅ 常時起動で 0ms | ✅ 構造的に 0ms |
| 実行時間上限 | △ 15分 | ✅ 制限なし | ❌ CPU 50ms |
| ランタイム自由度 | ✅ 多言語 | ✅ 任意コンテナ | ❌ Web API のみ |
| 低トラフィックコスト | ✅ 従量(ほぼ $0) | ❌ 常時課金 | ✅ 無料枠 1,000 万リク |
| グローバル低レイテンシ | △ 単一リージョン | △ 単一リージョン | ✅ 300+ PoP |
| 運用複雑さ | △ VPC・IAM・GW | ❌ ECS・ALB・SG | ✅ wrangler 1コマンド |
3つのサービスは競合ではなく、処理の層をどこで処理するかを設計する素材だ。実務では「認証・キャッシュは Workers、ビジネスロジックは Lambda、常駐サービスは Fargate」という組み合わせが最もコスト効率と運用性を両立する。
「とりあえず Lambda」ではなく「この処理特性だから Lambda」と言えること——その選択根拠を言語化できるエンジニアが、適切なコストとパフォーマンスのバランスを設計できる。
この記事をシェア