「コンテナをAWSで動かしたい。でも Fargate・Lambda・App Runner のどれを選べばいいかわからない」——スタートアップでバックエンドを本番に出すとき、この三択で立ち止まる場面は頻繁に起きます。選定に迷う理由は明確で、3つのサービスがそれぞれ"サーバーレス"を標榜しながら、対象とするワークロードと制約が全く異なるからです。
私は経済産業大臣賞を受賞した木材流通B2B SaaSで、API Gateway → NLB → ALB → ECS on Fargate という構成で 221本のAPIエンドポイントを本番運用しています。決済基盤では本番二重課金0件を実現し、バッチ・イベント駆動ワーカーもすべてFargateで回しています。この実装経験から、選定ミスがどれだけコストを生むかを身をもって知っています。
この記事は、「どれを選ぶべきか」という買い手意図の問いに正面から答える選定ガイドです。各サービスの本質・比較表・ユースケース別の即答・意思決定ツリーを一気通貫で提供します。Fargateの実装詳細は姉妹記事の AWS ECS on Fargate 本番運用ガイド に委ね、本稿は**「どれを選ぶか」の判断**に集中します。
選定ミスのコスト
まず「なぜ選定が重要か」を押さえます。後から気付く典型的な失敗パターンは次の3つです。
- Lambda で長時間処理を作ったが、15分で打ち切られる。機械学習推論・大容量CSVバッチ・動画処理で頻出。SQSキューで分割しても設計が複雑化し、Fargateに書き直すことになる。
- App Runner でプライベートRDSに繋げなかった。VPCコネクタを後から追加できるが、ネットワーク設計を最初から考慮していないと詰まる。
- Fargate を WebSocket なしで使い始めてからリアルタイム要件が出た。Fargate は NLB 経由で WebSocket 常駐ができるが、App Runner にはその制御がない。
選定ミスは移行コスト(再設計・再実装・再デプロイ)として技術的負債に変わります。最初に正しく選ぶことが、中長期のチームの速度を守ります。
3つのサービスの本質
AWS Lambda:イベント駆動の関数、スケールトゥゼロ
Lambdaはリクエストや非同期イベントが来たときだけ関数が起動し、処理が終わったら消えるイベント駆動の実行モデルです。アイドル時間の課金はゼロ——これがスケールトゥゼロの核心です。
制約も明確です。最大実行時間は15分(900秒)。同期呼び出し(API Gateway/ALB経由)のペイロード上限は6MB、非同期は256KB。コンテナイメージの場合も最大10GBですが、実行時間の制約は変わりません。メモリは128MB〜10,240MB(10GB)の範囲で割り当て、割り当てメモリに比例してvCPUも増えます。料金はリクエスト数+GB-秒(割り当てメモリ × 実行時間)の従量制です。
コールドスタートの存在も考慮が必要です。VPC内Lambdaは特にENI確保のコールドスタートが数百ms〜数秒に達することがあり、レイテンシ要件が厳しいAPIではProvisioned Concurrencyが必要になります(追加コスト)。
Lambdaが輝く場所:トラフィックが不規則・スパイキーで平均的にアイドルが多い。15分以内で終わる。ペイロードが小さい。常駐コストをゼロにしたい。
AWS App Runner:フルマネージドのWebアプリ/API、最小運用
App Runnerは、コンテナイメージ(またはソースリポジトリ)を渡すだけでHTTP/HTTPSのWebアプリ・APIを稼働させるフルマネージドサービスです。ロードバランサの設定・ECSクラスタ・タスク定義・サービス定義・容量プロバイダ——これらの概念がすべて隠蔽されます。
スケールは同時接続数ベースで自動。設定したminインスタンス数まで縮小しますが、完全なゼロには下がりません(minを1以上に設定した場合、アイドル中もプロビジョンドインスタンスが課金されます)。VPC接続はVPCコネクタを使えば可能ですが、SG・サブネットの細かな制御はECSほど柔軟ではありません。料金はプロビジョンドメモリ+アクティブ時のvCPUの組み合わせです。
App Runnerが輝く場所:HTTPのWebアプリ・内部APIを最速・最小運用で出したい。クラスタ管理やIaCを書く時間を割けない。プロトタイプ・MVP・社内ツール。
AWS Fargate(ECS):サーバーレスだが長時間・任意プロトコル・フルVPC制御
FargateはECS(Elastic Container Service)のサーバーレス起動タイプです。CPUとメモリを指定するだけでサーバー管理不要、かつ最大実行時間の制限がありません。任意のTCP/UDPプロトコルに対応し、awsvpcモードでENI・SG・サブネットをフルに制御できます。
タスクごとに独立した分離境界を持ち、カーネル・CPU・メモリ・ENIを他タスクと共有しません。タスクCPU/メモリは固定ペア(.25〜16 vCPU、最大120GB)から選択します。料金はvCPU秒+メモリ秒(最低1分)の従量制です。
HTTPサービスの常駐だけでなく、EventBridgeでのバッチ実行・SQSキュー駆動ワーカー・WebSocket常駐を、同じタスク定義の語彙で扱えるのが大きな強みです。Fargateのオートスケーリング・CI/CD(ブルーグリーン)・コスト最適化はそれぞれ専門記事があります。
Fargateが輝く場所:長時間処理・WebSocket常駐・任意プロトコル・きめ細かいVPCネットワーク制御・本番グレードのセキュリティ分離が必要なすべての場面。
比較表:3サービスを9つの観点で
| 観点 | Lambda | App Runner | Fargate(ECS) |
|---|---|---|---|
| 起動モデル | イベント駆動(関数) | 常駐(コンテナ) | 常駐 or 単発(コンテナ) |
| 最大実行時間 | 15分(900秒) | 制限なし | 制限なし |
| スケールトゥゼロ | 完全ゼロ(アイドル課金なし) | ゼロに下がらない(min課金) | ゼロに下がらない(min課金) |
| 対応プロトコル | HTTP/HTTPS中心(ALB/API GW) | HTTP/HTTPSのみ | 任意TCP/UDP(WebSocket・gRPC等) |
| VPCネットワーク制御 | VPC内実行可(コールドスタート増) | VPCコネクタ(部分的) | 完全制御(SG・サブネット・ENI) |
| 同時実行 | リクエスト単位で自動(アカウント上限あり) | 同時接続数ベース自動 | タスク数(desiredCount+Auto Scaling) |
| 料金モデル | リクエスト数+GB-秒 | プロビジョンドメモリ+アクティブvCPU | vCPU秒+メモリ秒(最低1分) |
| 運用の重さ | 最軽量(関数を書くだけ) | 軽量(コンテナを置くだけ) | 中(タスク定義・サービス・ALB・IaCが要る) |
| ロックイン | 高(実行モデルがAWS独自) | 中(App Runner固有の設定が増える) | 低(ECS APIはコンテナ標準に近い) |
制約の目安:Lambdaの同期ペイロード上限は6MB(リクエスト/レスポンス合算ではなく各方向)。コンテナイメージ使用時も実行時間制限(15分)は変わらない。
料金モデルの構造的な違い
具体的な金額は利用量・リージョン・コミットメントで大きく変わるため、ここでは**「いつ何に課金されるか」の構造**だけを整理します。
Lambda:使った分だけ
Lambdaの料金は「リクエスト数」と「実行時間(GB-秒)」の2軸です。タスクがアイドルのとき課金はゼロ。月に数百〜数千リクエストしか来ない機能や、夜間だけ動くバッチ、イベント量が読めないワークロードでは構造的に有利です。
ただし、Provisioned Concurrencyを使えばその分が常時課金に変わります。コールドスタート回避のために使い始めると、コストモデルがFargateに近づく点に注意が必要です。
App Runner:アイドルでもminインスタンス分は課金
App Runnerはプロビジョンドインスタンスのメモリに対して常時課金され、アクティブ実行時にはvCPUも課金されます。アイドル時間が長いほど、相対的にコストパフォーマンスが下がります。逆に常時トラフィックがある場合、自動スケール管理のオーバーヘッドを払わずに済む運用の軽さがコストに見合います。
Fargate:割り当て分に秒単位
Fargateはタスクが起動している間、割り当てたvCPU数とメモリ量に対して秒単位(最低1分)で課金されます。使用率100%でも10%でも、割り当て量は変わらないため、過剰なサイズ設定が最大のコスト漏洩になります。Graviton(ARM64)・Fargate Spot・Compute Savings Plansの組み合わせで最適化します(詳細はコスト最適化記事、またFinOpsの全体観はAWSコスト最適化・FinOps)。
ユースケース別の即答
迷わないために、代表的なワークロードごとに選択肢を示します。
HTTP API / Webアプリ(常時稼働)
- App Runner:最も速く出せる。ECSもALBも書かなくてよい。VPC制御が不要でHTTPSだけ提供するなら第一候補。
- Fargate:プライベートVPC内のDB・KMS・詳細なSGが必要、またはgRPC・WebSocketが要る場合。本番グレードの制御が必要な場合の本命。
- Lambda:トラフィックが極めて不規則で常時稼働コストを払いたくない場合。ただしコールドスタートとペイロード制限に注意。
cron / スケジュールバッチ
- Lambda:15分以内で完結するバッチの第一候補。EventBridge Schedulerとの組み合わせがシンプル。
- Fargate:15分超のバッチ、またはバッチ実行中のメモリが数GB超になる処理。EventBridge Scheduler +
RunTaskAPIで単発起動し、完了したら課金が止まる。
イベント駆動ワーカー(SQS・SNS・EventBridge)
- Lambda:キューをトリガーにする場合の定番。ポーリング設定(バッチサイズ・ウィンドウ・最大並行度)をLambdaイベントソースマッピングで管理できる。
- Fargate:処理時間が15分を超える、1メッセージあたりのペイロードが6MBを超える、またはSQSワーカーを独立したコンテナとして運用したい場合。決済基盤のWebhook処理はこのパターン。
長時間処理(動画変換・ML推論・大容量CSV)
- Fargate:一択に近い。最大実行時間の制限なし、タスクメモリ最大120GB、バッチ完了後に課金が止まる。
- Lambda + SQS分割は回避策として成立しますが、設計の複雑さとデバッグコストが上がります。
WebSocket 常駐(リアルタイム・双方向通信)
- Fargate:NLB経由でWebSocket接続を長時間維持できる。任意TCPプロトコルに対応している点が決定打。
- App Runnerは原則としてHTTP/HTTPSのリクエスト・レスポンスモデルを前提としており、長時間コネクションの維持は保証されません。
- LambdaはAPI Gateway WebSocket APIと組み合わせれば接続管理をAPIGWに委ねる方法はありますが、設計が非同期イベント中心になり、状態管理の複雑さが増します。
機械学習推論・AI バックエンド
- 応答時間が短く(5秒以内)、ステートレスなスコアリング:Lambda(コールドスタートが許容できる場合)。
- GPU不要・メモリ数GBの推論バッチや長時間推論:Fargate。
- GPU(NVIDIA等)が必要:FargateはGPU非対応のため、EC2起動タイプかSageMaker Endpointsが対象外条件で浮上します。
社内ツール / 管理画面
- App Runner:最速で出してすぐ使い始められる。Cognitoとの統合もシンプル。
- 認証・ネットワーク制御が厳しい場合(VPC内にしか公開できないなど):Fargate。
移行可能性:選定を誤ったときの地続き
選定は完全に取り消せなくてもグラデーションで移行できます。
Lambda → Fargate
Lambda関数を「コンテナイメージを動かすHTTPサーバー」に書き直すのが最小ステップです。Lambda Web Adapter(AWS製)を使えばExpressなどの既存サーバーをほぼそのままLambdaで動かしつつ、後でFargate上でも同じコンテナイメージを使えます。ただし実行モデル(イベント駆動 vs 常駐)の発想の違いがコード設計に影響するため、冪等性・グレースフルシャットダウン・コネクションプールの設計は書き直しが必要になることがほとんどです。
App Runner → ECS(Fargate)
App RunnerとECS on Fargateはどちらもコンテナイメージをベースにするため、イメージ自体の書き直しはほぼ不要です。主な移行コストはインフラ層——ECSタスク定義・サービス・ALB・SG・IAMロールをIaCで書く作業です。コンテナコードには触らずネットワーク制御とIAMを整備すれば移行できることが多く、「最初はApp Runnerでプロトタイプ→本番化でECS」は合理的なエスカレーションパスです。ただしApp Runner固有の環境変数名や設定ファイルをアプリに埋め込んでいると、その差分の吸収が増えます。
意思決定ツリー
次の問いを順に答えることで、選択肢が絞れます。
Q1. 最大実行時間は 15 分以内に収まるか?
├── No → Fargate(制限なし)
└── Yes → Q2 へ
Q2. HTTP/HTTPS 以外のプロトコル(WebSocket・gRPC・UDP 等)が必要か?
├── Yes → Fargate(任意TCP/UDP対応)
└── No → Q3 へ
Q3. プライベートVPC内のリソース(RDS・ElastiCache等)への細かいSG制御、
またはENI直結のアドレス管理が必要か?
├── Yes → Fargate(awsvpc でフルVPC制御)
└── No → Q4 へ
Q4. トラフィックはスパイキー・不規則で、アイドル時間が多い想定か?
├── Yes → Lambda(スケールトゥゼロ、アイドル課金ゼロ)
└── No → Q5 へ
Q5. ALB・ECSクラスタ・タスク定義・IaCを書く手間を省き、
最速で HTTP API を本番に出したいか?
├── Yes → App Runner(最小運用)
└── No → Fargate(将来の拡張余地が最も広い)
判断の補助メモ:
- 「迷ったらFargate」は概ね正しいですが、コストも運用の重さも増えます。トラフィックが小さく、アイドルが多い場合はLambdaが構造的に有利です。
- App Runnerはコントロールプレーンの管理コストが最小ですが、「VPCコネクタを後から追加する」「SG設定を細かく変えたい」が出てきた瞬間に、ECSへの移行を考え始めることになります。最初から本番グレードの制御が必要だとわかっているなら、Fargateから始める方が正直です。
- ECS on EKSの比較(Kubernetesが必要か)は ECS vs EKS スタートアップ意思決定フレームワーク を参照してください。
具体的な設定例
三者の違いを実感するために、同じ「Hello APIを本番に出す」タスクでの設定量を比べます。
App Runner:apprunner.yaml(最小)
version: 1.0
runtime: nodejs20
build:
commands:
build:
- npm ci --omit=dev
- npm run build
run:
command: node dist/server.js
network:
port: 3000
env: APP_PORT
env:
- name: NODE_ENV
value: production
これだけです。ALBもECSサービスもSGもIAMロールも、App Runnerが隠蔽します。ソースリポジトリと紐づければ、プッシュのたびに自動デプロイされます。VPCコネクタ・シークレット・カスタムドメインはコンソールかTerraformのリソース設定で追加します。
Lambda:ハンドラ vs Fargate:常駐HTTPサーバー(対比)
// Lambda ハンドラ — イベント駆動、呼ばれるたびに起動
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
const body = JSON.parse(event.body ?? "{}");
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: "ok", input: body }),
};
};
// 接続プールは起動ごとに再利用(コンテナが温かければ)
// ただし実行時間は 15 分で打ち切られる
// Fargate 上の常駐 HTTP サーバー — 起動後ずっと待機
import http from "node:http";
import { installGracefulShutdown } from "./graceful-shutdown.js";
const server = http.createServer((req, res) => {
if (req.url === "/healthz") {
res.writeHead(200).end("ok");
return;
}
let body = "";
req.on("data", (chunk) => { body += chunk; });
req.on("end", () => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "ok", input: JSON.parse(body || "{}") }));
});
});
server.listen(8080, () => console.info({ msg: "listening", port: 8080 }));
// SIGTERM を握ってデプロイ時に綺麗に終わる(Fargate の本番必須)
installGracefulShutdown(server, {
drainMs: 50_000, // stopTimeout(60s) より短く
onClose: async () => {
await db.end(); // DB コネクションプールを閉じる
await queue.close(); // SQS コンシューマを止める
},
});
// 実行時間の制限なし。WebSocket や gRPC も同じプロセスで扱える
Fargateではプロセスが常駐しているため、DB接続プールを起動時に1回だけ確立し、全リクエストで使い回せます。Lambdaでもウォームスタートでコンテナを再利用できますが、それはベストエフォートであり保証されません。常駐サービスとしてのコネクションプーリングが必要なら、Fargateが本命です。
Fargate タスク定義の最小骨格(JSON)
Fargateの場合、App Runnerのapprunner.yamlに相当する設定がタスク定義です。このボリュームがApp Runnerとの「運用の重さ」の差を示しています。
{
"family": "hello-api",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::ACCOUNT_ID:role/hello-api-exec",
"taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/hello-api-task",
"containerDefinitions": [
{
"name": "app",
"image": "ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-api:abc1234",
"essential": true,
"portMappings": [{ "containerPort": 8080, "protocol": "tcp" }],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:ACCOUNT_ID:secret:prod/db"
}
],
"stopTimeout": 60,
"healthCheck": {
"command": ["CMD-SHELL", "wget -q -O - http://localhost:8080/healthz || exit 1"],
"interval": 15,
"timeout": 5,
"retries": 3,
"startPeriod": 30
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/hello-api",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "app"
}
}
}
]
}
さらにこれに加えて、ECSサービス・ALB・ターゲットグループ・SG・IAMポリシーをTerraformで書く必要があります。この重さと引き換えに得られるのが、VPCの完全制御・デプロイサーキットブレーカー・Fargate Spot混在・ECS Execなど本番グレードの制御です。
実プロジェクトでの選定例
私の実務でどう使い分けているかを参考として示します。
経済産業大臣賞受賞の木材流通B2B SaaSでは:
- HTTPサービス(221エンドポイント)→ Fargate:VPC内のRDS(PostgreSQL)・ElastiCacheへの接続、Cognito RS256検証のJWTミドルウェア、詳細なSG制御が必要だったため。
- Stripe Webhook処理 → Fargate(SQSワーカー):Webhookの重複・順不同を冪等キーで吸収し、1メッセージの処理がDBトランザクションを含むため15分制限内でも収まるが、接続プールの安定性とグレースフルシャットダウンの厳密さを優先してFargateを選択。
- 軽量な通知メール送信 → Lambda(EventBridge Pipes経由):DynamoDB Streamsをトリガーに数秒で完結する処理。アイドル時間が長くスケールトゥゼロの恩恵が大きい。
「一人 × 生成AI(Claude Code)」で速く・安く・安全に作る私のやり方では、選定の正確さが後工程の速度を決めます。人間が検証ゲートを持ち、選定段階から正しい層を選んでいることが、後からの作り直しを防ぐ最大のリスクヘッジです。
まとめ:選定の起点は3つの問い
AWS Fargate・Lambda・App Runnerの選定は、次の3つの問いで決まります。
- 最大実行時間は15分以内か? → No なら Fargate 一択。
- HTTP/HTTPS 以外のプロトコルやきめ細かいVPC制御が必要か? → Yes なら Fargate。
- トラフィックがスパイキーでアイドルが多く、運用を最小にしたいか? → LambdaまたはApp Runner。
「迷ったらFargate」は後から変えやすいですが、コストと運用の重さが増えます。「まず Lambda/App Runner で出して詰まったら移行」は移行コストとして技術的負債になります。最初の選定に正確さを投資することが、長期的なチームの速度と安定を守ります。
本番Fargateの実装詳細(タスク設計・ネットワーキング・デプロイ・セキュリティ・コスト最適化)は AWS ECS on Fargate 本番運用ガイド にまとめています。コンテナ基盤の設計・選定・構築を速く・安く・安全に進めたい場合は、ぜひご相談ください。