Serverless (Lambda/Fargate) vs Edge (Cloudflare):処理特性に応じたリソースの使い分け

|
AWS Lambda Fargate Cloudflare Edge Serverless アーキテクチャ

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」と言えること——その選択根拠を言語化できるエンジニアが、適切なコストとパフォーマンスのバランスを設計できる。

この記事をシェア

Twitter / X LinkedIn
記事一覧に戻る
🤖
Cloud Assistant
IBM Watson powered

こんにちは!クラウドエンジニアのポートフォリオサイトへようこそ。AWS構成・副業サービス・お仕事のご相談など、何でも聞いてください 👋