- 1 Serverless本番運用入門 Vol1 — Lambda × API Gateway × Step Functions
- 1.1 1. なぜServerless本番運用か — 全11軸からの架橋 + 第12軸結節点
- 1.2 2. AWS Serverless 3本柱整理 + サービスマップ
- 1.3 3. Lambda 本番運用 ★山場1 — Cold Start × VPC × Provisioned Concurrency × Lambda Insights
- 1.3.1 3-1. Lambda 関数設定 — Memory / Timeout / Ephemeral Storage
- 1.3.2 3-2. Cold Start 構造 (Init phase / Invoke phase / Provisioned Concurrency の挙動)
- 1.3.3 3-3. Cold Start 対策3パターン
- 1.3.4 3-4. VPC 接続 — ENI 管理 / Subnet 設計 / Security Group
- 1.3.5 3-5. IAM Role 最小特権
- 1.3.6 3-6. Memory Tuning + Lambda Insights
- 1.3.7 3-7. Terraform 例: Lambda 本番構成
- 1.4 4. API Gateway 本番運用 ★山場2 — HTTP API vs REST × 認証3方式 × Throttling × CORS × Custom Domain
- 1.4.1 4-1. HTTP API vs REST API — 選定軸と本番判断基準
- 1.4.2 4-2. HTTP API 認証3方式
- 1.4.3 4-3. REST API 認証設計 — Cognito / Lambda Authorizer / IAM / API Key + Usage Plan
- 1.4.4 4-4. Custom Authorizer 設計 — TOKEN vs REQUEST / Cache TTL
- 1.4.5 4-5. Throttling — Account-level / Stage-level / Method-level / Usage Plan
- 1.4.6 4-6. CORS 設定 + Custom Domain
- 1.5 5. Step Functions 本番運用 ★山場3 — Standard vs Express × Distributed Map × Callback Pattern × Error Handling × SDK Direct
- 1.5.1 5-1. Standard vs Express — 選定軸
- 1.5.2 5-2. Distributed Map — 大規模並列バッチ
- 1.5.3 5-3. Callback Pattern — waitForTaskToken
- 1.5.4 5-4. Error Handling — Retry / Catch / 指数バックオフ
- 1.5.5 5-5. SDK Direct Integration — Lambda不要で AWS API を直接呼び出し
- 1.5.6 5-6. ASL 設計 + I/O Filter
- 1.5.7 5-7. deep-dive 記事クロスリンク
- 1.5.8 5-8. Terraform 実装例
- 1.6 6. 詰まりポイント7選 — Cold Start遅延 / VPC ENI / Lambda timeout / APIGW throttle / SF状態爆発 / IAM hell / Cost runaway
- 1.6.1 詰まり1: Cold Start p99 遅延 — VPC ENI 初期化 + 大型 Container Image が重なると 8 秒超
- 1.6.2 詰まり2: VPC ENI 枯渇 — 旧設計で同時実行ごとに ENI 1個消費
- 1.6.3 詰まり3: Lambda Timeout vs API Gateway 29秒制限の衝突
- 1.6.4 詰まり4: API Gateway Throttling — Account-level 制限で全テナントが被害を受ける
- 1.6.5 詰まり5: Step Functions 状態爆発 — Map state で履歴 25K 制限に抵触
- 1.6.6 詰まり6: IAM Role 設計の複雑化 — Serverless 4 Role を整理する
- 1.6.7 詰まり7: Cost Runaway — Provisioned Concurrency 過剰確保と Standard Workflow 過剰実行
- 1.7 7. アンチパターン→正解パターン変換演習 (5件)
- 1.8 8. まとめ + Vol2予告 + 落とし穴10選 + 全11軸クロスリンク + 第12軸完結宣言
Serverless本番運用入門 Vol1 — Lambda × API Gateway × Step Functions

本記事は AWS本番運用 全11軸 (IAM/EKS/復旧/AI/セキュリティ/コスト/マルチアカウント/Observability/Network/DevOps/Database) を完遂した中堅エンジニアに向けた、第12軸 = Serverless本番運用 の起点記事です。Lambda × API Gateway × Step Functions の3本柱 (Compute / API / Workflow) を全11軸統合視点で再統合し、本番品質の Serverless 運用パターンを確立します。
前11軸シリーズ (23記事)
- IAM Vol1-4 / EKS Vol1-3 / 復旧 Vol1-4 / AI Vol1-2 / セキュリティ Vol1-2 / コスト Vol1 / マルチアカウント Vol1 / Observability Vol1 / Network Vol1-2 / DevOps Vol1-2 / Database Vol1
関連シリーズ (Serverless 個別 deep-dive)
- Lambda deep-dive: Container Image / Powertools+Layers / SnapStart / Authorizer (4本)
- Step Functions deep-dive: Express vs Standard / Distributed Map / Callback Pattern / Error handling / SDK Direct Integration / IO Filters / DataFlow / ECS Job連携 (10本以上)
- API Gateway deep-dive: Lambda Authorizer Production
1. なぜServerless本番運用か — 全11軸からの架橋 + 第12軸結節点
IAM・EKS・復旧・AI・セキュリティ・コスト・マルチアカウント・Observability・Network・DevOps・Database の全11軸 23記事を完遂した読者は、次の問いに直面する。「アプリケーションロジックをどう実行し、API として公開し、複雑なワークフローを安全に完走させるか」。インフラは整った。しかし Serverless 領域の本番品質運用を体系化していないと、Cold Start 遅延・VPC 制約・API 設計ミス・Step Functions ステート爆発などのペインが蓄積していく。本 Vol1 は第12軸 Serverless本番運用シリーズの起点として、Lambda × API Gateway × Step Functions の3本柱を全11軸統合視点で再統合し、本番品質の Serverless 運用パターンを確立する。
全11軸完遂後の「次の壁」
全11軸を完遂した中堅エンジニアが Serverless 設計に踏み込むとき、Application 層だけでは解決できない5つの壁が立ちはだかる。
壁1: Compute層の選定と Cold Start 管理
Lambda は起動コスト (Cold Start) が p99 レイテンシに直撃する。init フェーズのコンテナ初期化・ランタイム起動・ハンドラロードの3段階を正しく理解しないまま Provisioned Concurrency を設定すると、コストが数十倍に膨れ上がる。Container Image 形式と ZIP デプロイでは Cold Start 特性が異なり、SnapStart (Java/Python/.NET) の適用条件も限定的だ。3本柱のうち最も運用パラメータが多いのが Lambda であり、Memory/Timeout/Ephemeral Storage/VPC attachment の組み合わせが本番品質を左右する。
壁2: VPC ENI 枯渇事故
Lambda を VPC 内に配置すると、同時実行数の増加に比例して ENI (Elastic Network Interface) を消費する。ENI の作成には数十秒かかることがあり、急激なスパイク時に ENI プールが枯渇すると Lambda 起動自体が失敗する。EKS × Lambda 混在環境や、Database Vol1 で導入した RDS/Aurora への接続を Lambda から行う構成では、RDS Proxy の導入が必須になる。VPC 設計 (Network Vol1-2) の知識と Serverless の接続管理が統合されて初めて安全な本番運用が成立する。
壁3: API Gateway スロットリングと認証設計
API Gateway はデフォルトで リージョン単位のスロットリング上限 (10,000 RPS) と アカウント単位の上限 が存在する。HTTP API と REST API の選択を誤ると、後から必要な機能 (Usage Plan / Lambda Authorizer / API Key 管理) が利用できなくなる。Cognito Authorizer・Lambda Authorizer・IAM 認証の3方式を適切に選択しないと認証バイパスのリスクが残る。
壁4: Step Functions ステート爆発
Step Functions のステートマシン定義 (ASL: Amazon States Language) は、複雑な分岐・並列処理・エラーハンドリングを加えると状態数が爆発的に増える。Standard Workflow と Express Workflow の選択基準を誤ると、実行履歴の保持期限切れ・コスト超過・デバッグ困難が発生する。Distributed Map (10万件並列処理) や Callback Pattern (外部サービス待機) の本番運用は、既存の Step Functions 実践編 deep-dive が詳細を扱っており、本 Vol1 ではその統合視点を提供する。
壁5: IAM Role 設計の複雑化
Serverless 構成では Lambda 実行ロール・API Gateway ロール・Step Functions 実行ロール・EventBridge ルールロールと、サービスごとに IAM Role が増殖する。IAM Vol1-4 で習得した最小権限設計・SCP・Permission Boundary の原則を Serverless 文脈に適用する設計パターンが必要だ。特に Lambda から DynamoDB/RDS/Secrets Manager へのアクセスは、リソースベースポリシーと実行ロールの両面から制御する。
本 Vol1 で得られる4つの成果
3本柱選定フレームワーク — Compute (Lambda) / API (API Gateway) / Workflow (Step Functions) の役割分担と選定マトリクス。実行時間・同時実行数・Stateful度・コストの4軸で最適解を導く手順。
Lambda 本番運用 — Cold Start 対策 (Provisioned Concurrency / SnapStart / Container Image 最適化)・VPC ENI 管理・RDS Proxy 連携・Lambda Insights によるオブザーバビリティ。実 SAM/Terraform テンプレートで再現可能な本番品質設定を提供する。
API Gateway 本番運用 — HTTP API vs REST API 選定・Cognito/Lambda/IAM 認証3方式・スロットリング設計・カスタムドメイン設定・Usage Plan 管理。API Gateway × Lambda の統合パターンを IaC で完全定義する。
Step Functions 本番運用 — Standard/Express 選定・Distributed Map 本番運用・Callback Pattern・エラーハンドリング設計。既存 deep-dive 資産 (10本以上) への橋渡しと、本番品質マシン定義のテンプレートを提供する。
既存 deep-dive シリーズとの住み分け
本 Vol1 は 統合俯瞰ハブ記事 として位置付ける。Lambda / Step Functions / API Gateway の各 deep-dive シリーズは引き続き「個別深掘りの素材」として尊重する。
| カテゴリ | 既存 deep-dive (個別深掘り) | 本 Vol1 の役割 |
|---|---|---|
| Lambda | Container Image / Powertools+Layers / SnapStart / Authorizer (4本) | Cold start × VPC × PC の統合本番設定 |
| Step Functions | Express vs Standard / Distributed Map / Callback / Error / SDK直接統合 / IO Filters / DataFlow (10本以上) | Standard/Express選定 + 本番品質起点 |
| API Gateway | Lambda Authorizer Production | HTTP vs REST × 認証3方式統合 |
既存の deep-dive 記事を読んだ読者は、本 Vol1 で「全体がどうつながるか」を把握できる。本 Vol1 を読んだ読者は、各 deep-dive 記事で「特定技術を深く掘り下げる」ことができる。
痛点5選: Serverless 本番運用の地雷
痛点1: Cold Start での p99 遅延急増
Lambda 関数がトラフィックスパイク後にスケールアウトすると、新規コンテナの init フェーズが p99 レイテンシを急増させる。Provisioned Concurrency を設定しても Application Auto Scaling で適切にスケジュール設定しないと、朝9時のトラフィック増加時に未準備のコンテナが Cold Start を引き起こす。SnapStart は Java 環境では有効だが、Lambda 関数のコード変更のたびに Snapshot 作成が走り、デプロイ時間が増加する副作用がある。
痛点2: VPC ENI 枯渇事故
RDS Aurora への接続のために Lambda を VPC 内に配置したところ、同時実行数が 500 を超えた時点で ENI 作成待ちによる ResourceNotReadyException が多発した事例がある。対策は RDS Proxy の導入 (コネクションプーリング)、および Lambda Subnet に十分な IP アドレス空間を確保すること。/24 サブネット (254 IP) では容量不足になるケースがあり、/20 以上の割り当てが推奨される。
痛点3: API Gateway スロットリング設定漏れ
デフォルトの API Gateway は Usage Plan 未設定の状態で本番公開すると、スクレイピングや過負荷アクセスパターンでアカウント全体のスロットリング上限に達し、他の API も巻き込んでレート制限される。HTTP API と REST API では Usage Plan の設定方法が異なり、HTTP API には Usage Plan が存在しない (Lambda 関数側でレート制御が必要)。
痛点4: Step Functions ステート数上限
Standard Workflow は実行あたり最大 25,000 状態遷移の上限がある。大規模な Distributed Map (S3 CSV 100万行処理等) でネストが深くなると、状態遷移数の上限超過で実行が失敗する。対策は Express Workflow への切り替えまたは処理単位の分割。ただし Express Workflow には実行履歴の保持期限 (90日) とイベント数上限があり、監査要件がある場合は CloudWatch Logs との連携設計が必要になる。
痛点5: Lambda × RDS 接続数枯渇
Lambda のコンカレンシーが増加すると各コンテナが独立して DB コネクションを確立するため、RDS/Aurora の接続数上限 (max_connections) を瞬時に超過する。RDS Proxy を経由することでコネクションプーリングが機能するが、RDS Proxy 自体にも同時接続数の上限 (インスタンスクラス依存) があるため、負荷試験で確認が必要だ。Database Vol1 で設計した RDS/Aurora 構成と本 Vol1 の Lambda 接続設計は密接に連動する。
対象読者と前提スキル
本 Vol1 の対象読者は、AWS 本番運用の全11軸 (IAM/EKS/復旧/AI/セキュリティ/コスト/マルチアカウント/Observability/Network/DevOps/Database) を一通り経験し、Serverless 本番運用を体系的に整理したい中堅エンジニアだ。
前提スキル:
– Lambda 関数の基本的なデプロイ・実行経験
– API Gateway での REST API または HTTP API 作成経験
– Step Functions の基本ステートマシン作成経験 (あれば望ましい)
– SAM または Terraform での IaC 経験
– IAM Role / ポリシー設計の基礎知識 (IAM Vol1-4 相当)
Serverless 本番運用 5原則
全11軸の経験を経て Serverless に取り組む際、以下の5原則を設計の基軸にすることで痛点の多くを事前に防げる。
ステートレス設計の徹底 — Lambda 関数は呼び出しをまたいで状態を持たない前提で設計する。状態が必要なら DynamoDB・ElastiCache・Step Functions に委ねる。
/tmpの再利用は許容するが依存してはならない。コンカレンシー予算の明示 — Lambda のデフォルト同時実行上限 (アカウント 1,000) は全関数で共有される。本番 API に Reserved Concurrency を設定し、重要でない関数がコンカレンシーを枯渇させないよう予算配分する。
べき等性の保証 — SQS トリガーの Lambda は at-least-once で呼ばれる。同一イベントを2回処理しても副作用が出ない設計 (DynamoDB 条件付き書き込み・冪等キー管理) が必須だ。
タイムアウト連鎖の設計 — API Gateway (29秒) → Lambda (設定値) → RDS Proxy (接続タイムアウト) の3層それぞれにタイムアウトが存在する。上流のタイムアウトが下流より短いと、処理が続いているのに上流がエラー返却するという不整合が生まれる。
オブザーバビリティファースト — Lambda Insights・X-Ray・Structured Logging (AWS Lambda Powertools) を最初から有効化する。Cold Start 頻度・p99 レイテンシ・エラー率の3指標を CloudWatch Dashboard で常時監視する体制を最初から整える。
本記事の各セクション構成
| § | タイトル | 主要内容 |
|---|---|---|
| §1 | なぜServerless本番運用か | 全11軸からの架橋・痛点5選・住み分け |
| §2 | AWS Serverless 3本柱整理 + サービスマップ | 3本柱定義・選定マトリクス・統合アーキテクチャ |
| §3 | Lambda 本番運用 ★山場1 | Cold Start × VPC × Provisioned Concurrency × Lambda Insights |
| §4 | API Gateway 本番運用 ★山場2 | HTTP vs REST × 認証3方式 × スロットリング × カスタムドメイン |
| §5 | Step Functions 本番運用 ★山場3 | Standard/Express選定 × Distributed Map × Callback × エラー設計 |
| §6 | 3本柱統合設計パターン | API GW → Lambda → Step Functions 実践IaC |
| §7 | 詰まり7選 + 演習5問 | 実際の障害事例と解決パターン・理解確認問題 |
| §8 | 全11軸+第12軸 クロスリンク | 関連記事ナビ |
- 第1軸: IAM (4記事)
Vol1: IAM ポリシー設計入門 /
Vol2: マルチアカウント IAM 設計 /
Vol3: Permission Inventory 自動化 /
Vol4: STS クロスアカウント - 第2軸: EKS本番運用 (3記事)
Vol1: クラスター設計 / IRSA / ALB Ingress /
Vol2: Observability / Fluent Bit / Container Insights /
Vol3: GitOps / ArgoCD - 第3軸: 復旧・運用 (4記事)
Vol1: Backup × Cross-Region DR /
Vol2: Chaos Engineering × FIS /
Vol3: ランブック × 自動化 /
Vol4: Multi-Region Active-Active - 第4軸: AIシリーズ (2記事)
Vol1: Bedrock Agents 本番運用 /
Vol2: Knowledge Bases × RAG - 第5軸: セキュリティ本格運用 (2記事)
Vol1: セキュリティ運用入門 /
Vol2: SOC 統合運用 - 第6軸: コスト最適化 (1記事)
Vol1: Cost Explorer × Budgets × Compute Optimizer - 第7軸: マルチアカウント運用 (1記事)
Vol1: Organizations × Control Tower × Landing Zone - 第8軸: Observability (1記事)
Vol1: Application Signals × SLO × X-Ray - 第9軸: Network/VPC設計 (2記事)
Vol1: Transit Gateway × VPC Lattice × PrivateLink /
Vol2: Hybrid Connectivity (Direct Connect × VPN) - 第10軸: DevOps/CI/CD (2記事)
Vol1: CodePipeline × CodeBuild × CodeDeploy × GitHub Actions OIDC /
Vol2: Container × CodeArtifact × SAM × Amplify - 第11軸: Database本番運用 (1記事)
Vol1: Database本番運用入門 — RDS × Aurora × DynamoDB - 第12軸: Serverless本番運用 (本記事)
Vol1: Lambda × API Gateway × Step Functions (本記事) - Terraform基礎入門 — Terraform 1.x×AWS Provider 6.x (S3×EC2×Remote State×Module化)
2. AWS Serverless 3本柱整理 + サービスマップ
AWS Serverless の全体像を把握するには、まず3本柱の役割分担を明確にする必要がある。Lambda・API Gateway・Step Functions はそれぞれ独立したサービスだが、実際の本番システムでは3つが連携して動作する。3本柱のどれが欠けても本番品質の Serverless アーキテクチャは成立しない。このセクションでは3本柱の定義・AWSサービス全体マップ・選定マトリクス・統合アーキテクチャパターンを整理する。
3本柱の定義
Compute (Lambda)
Lambda は AWS の FaaS (Function as a Service) であり、Serverless アーキテクチャの中心的な Compute 層だ。イベント駆動で実行され、サーバーのプロビジョニング・管理が不要なのが特徴。実行環境 (Execution Environment) は使い回され、コールド/ウォームスタートの概念を理解することが本番運用の鍵になる。Lambda が担うのは「ビジネスロジックの実行」であり、変換・検索・集計・外部API呼び出しなどのステートレスな処理に最適だ。
主要な機能:
– Function URL: HTTP エンドポイントを Lambda に直接割り当て。API Gateway を経由しない軽量な API 公開
– Container Image: 最大 10GB のコンテナイメージでデプロイ。依存ライブラリが大きいML推論や複雑な処理に対応
– Lambda Layer: 共通ライブラリ・設定をレイヤーとして管理。複数関数間で再利用可能
– SnapStart: Java/Python/.NET の init フェーズを事前に Snapshot 化して Cold Start を削減
– Provisioned Concurrency: 指定した数の実行環境を事前ウォームアップし、Cold Start を排除
API (API Gateway)
API Gateway は API 公開・認証・スロットリング・バージョン管理を担う Managed API 層だ。Lambda のトリガーとして最も一般的に使われ、HTTP リクエストを Lambda に変換して返す。REST API・HTTP API・WebSocket API の3種類があり、用途に応じた選択が重要だ。
主要な機能:
– HTTP API: 低レイテンシ・低コストの API エンドポイント。JWT/Lambda 認証対応。Usage Plan 非対応
– REST API: 完全な機能セット。Usage Plan / API Key / Request Validation / Response Mapping 対応
– WebSocket API: 双方向リアルタイム通信。チャット・通知・ゲームに活用
– Custom Authorizer (Lambda Authorizer): リクエストの認証・認可をカスタム Lambda 関数で実装
– Usage Plan + API Key: クライアント別のスロットリング・クォータ管理
– Throttling: Burst Limit と Rate Limit でスパイクアクセスから Lambda を保護
Workflow (Step Functions)
Step Functions はステートマシンとしてのワークフロー管理層だ。複数の Lambda 関数・AWS サービス呼び出しを ASL (Amazon States Language) で定義し、処理の順序・分岐・並列・エラーハンドリング・リトライを可視化して管理する。Lambda だけでは実現困難な「長時間処理」「複雑な分岐」「ヒューマンアプルーバル待機」を安全に実装できる。
主要な機能:
– Standard Workflow: 最大 1 年間の実行。完全な実行履歴・監査対応。高コスト
– Express Workflow: 最大 5 分の実行。高スループット向け。実行履歴は CloudWatch Logs
– Distributed Map: S3 / JSON 配列を並列処理。最大 10,000 並列。大規模バッチに活用
– Callback Pattern: .waitForTaskToken で外部サービス (承認フロー / SQS / SNS) の応答待機
– SDK直接統合: Lambda を介さず AWS サービス (DynamoDB / S3 / ECS 等) を直接呼び出し
AWS Serverless サービスマップ
3本柱を中心に、周辺サービスを含めたマップを整理する。
カテゴリ1: Compute (Lambda 中心)
| サービス/機能 | 説明 | 本番での主用途 |
|---|---|---|
| AWS Lambda | FaaS 本体 | ビジネスロジック実行 |
| Lambda Function URL | Lambda への直接 HTTP エンドポイント | 軽量 Webhook / 内部 API |
| Lambda Container Image | コンテナ形式デプロイ (最大 10GB) | ML 推論・大規模依存 |
| Lambda Layer | 共通ライブラリ管理 | Powertools / SDK 共通化 |
| Lambda SnapStart | Java/Python init Snapshot 化 | Cold Start 削減 |
| Provisioned Concurrency | 実行環境事前ウォームアップ | SLA 要件付き API |
| Lambda Insights | CloudWatch による Lambda 監視 | p99/エラー率/メモリ監視 |
カテゴリ2: API (API Gateway 中心)
| サービス/機能 | 説明 | 本番での主用途 |
|---|---|---|
| HTTP API | 低コスト API エンドポイント | 内部API / モバイルバックエンド |
| REST API | フル機能 API エンドポイント | 外部公開 / 課金管理あり |
| WebSocket API | 双方向リアルタイム通信 | チャット / 通知 |
| Lambda Authorizer | カスタム認証 Lambda | JWT / OAuth 独自検証 |
| Cognito Authorizer | Cognito User Pool 認証 | ユーザー認証済み API |
| Usage Plan + API Key | クライアント別スロットリング | B2B API 課金管理 |
| Custom Domain | 独自ドメイン設定 | 本番公開 URL |
カテゴリ3: Workflow (Step Functions 中心)
| サービス/機能 | 説明 | 本番での主用途 |
|---|---|---|
| Standard Workflow | 長時間・監査対応ワークフロー | 注文処理 / 承認フロー |
| Express Workflow | 高スループット短時間ワークフロー | ストリーミング処理 |
| Distributed Map | 大規模並列処理 (S3 / 配列) | ETL / バッチ処理 |
| Callback Pattern | 外部応答待機 | ヒューマンアプルーバル / SQS 連携 |
| SDK Direct Integration | AWS サービス直接呼び出し | DynamoDB / ECS 直接操作 |
カテゴリ4: Glue層 (統合サービス)
| サービス/機能 | 説明 | 本番での主用途 |
|---|---|---|
| EventBridge | イベントルーティング / スケジューラー | Lambda トリガー / サービス間連携 |
| SQS | メッセージキュー | Lambda 非同期トリガー / デカップリング |
| SNS | Pub/Sub 通知 | ファンアウト / アラート配信 |
| Kinesis Data Streams | リアルタイムストリーミング | ログ処理 / リアルタイム分析 |
| SAM (Serverless Application Model) | Serverless IaC フレームワーク | Lambda/API GW/Step Functions 定義 |
| CDK (Cloud Development Kit) | TypeScript/Python でインフラ定義 | 大規模 Serverless 構成管理 |
選定マトリクス: 4軸7パターン
実行時間・同時実行数・Stateful度・コストの4軸でサービス組み合わせを選定する。
| パターン | 実行時間 | 同時実行 | Stateful | コスト | 推奨構成 |
|---|---|---|---|---|---|
| 同期 API | ~29秒 | 中 (〜1000) | No | 低 | HTTP API + Lambda |
| 外部公開 API | ~29秒 | 中〜高 | No | 中 | REST API + Lambda + Usage Plan |
| リアルタイム | 持続 | 高 | No | 中 | WebSocket API + Lambda |
| 短時間バッチ | ~5分 | 高 | Yes | 低 | Express + Lambda |
| 長時間ワークフロー | ~1年 | 低〜中 | Yes | 高 | Standard + Lambda + SDK直接 |
| 大規模並列 | ~5分×並列 | 超高 | No | 中〜高 | Distributed Map + Lambda |
| イベント連携 | ~15分 | 高 | No | 低 | EventBridge + Lambda |
5ステップ判断フロー
Step1: 実行時間が 29秒を超えるか?
Yes → Lambda + Step Functions (Standard or Express)
No → API Gateway + Lambda を検討
Step2: 同時実行数が 10,000 RPS を超えるか?
Yes → HTTP API (低コスト) + Lambda Provisioned Concurrency
No → REST API + Usage Plan
Step3: Stateful な処理 (複数ステップ・承認待機) が必要か?
Yes → Step Functions (Standard: 監査あり / Express: 高スループット)
No → Lambda 単体 or Async invoke
Step4: 大規模データ並列処理 (10万件以上) が必要か?
Yes → Step Functions Distributed Map
No → Lambda + SQS (並列度は Lambda コンカレンシーで制御)
Step5: コスト重視か、機能重視か?
コスト → HTTP API + Lambda (最安)
機能 → REST API + Lambda (Usage Plan / Request Validation あり)
3本柱統合アーキテクチャパターン
パターン1: 同期 API + 軽量処理
Client
│
▼
API Gateway (HTTP API)
│ JWT / Cognito 認証
▼
Lambda (ビジネスロジック)
│
▼
DynamoDB / RDS Proxy → Aurora
HTTP API で低コスト・低レイテンシ。Lambda は同期実行 (最大 29秒)。DynamoDB (ミリ秒応答) または RDS Proxy 経由 Aurora (コネクション管理)。
パターン2: 非同期ワークフロー + Step Functions
Client
│
▼
API Gateway (REST API)
│ Lambda Authorizer 認証
▼
Lambda (受付 + SQS 投入)
│
▼
SQS → Lambda (Step Functions 起動)
│
▼
Step Functions (Standard Workflow)
├─ Lambda (Step 1: データ検証)
├─ Lambda (Step 2: 外部API連携)
├─ Callback (承認待機)
└─ Lambda (Step 3: 結果永続化)
│
▼
DynamoDB / S3
REST API + Lambda Authorizer で認証。SQS でデカップリング。Step Functions Standard で監査可能なワークフロー管理。
パターン3: 大規模バッチ処理
EventBridge Scheduler (定期実行)
│
▼
Lambda (ジョブ開始 + S3 一覧取得)
│
▼
Step Functions (Distributed Map)
│ 並列 10,000 ワーカー
▼
Lambda (各ファイル処理)
│
▼
S3 (処理結果) / DynamoDB (集計データ)
EventBridge Scheduler で定期起動。Distributed Map で S3 の CSV / JSON ファイルを並列処理。Express Workflow で高スループット + コスト最適化。
よくある誤り3選
誤り1: HTTP API と REST API の選択ミス
HTTP API を選んだ後、Usage Plan が必要になった・Request Validation が必要になった・WAF 統合が必要になった、などの理由で REST API への移行が発生するケースが多い。選択基準: B2B API / 外部公開 / 課金管理が必要なら REST API 一択。内部 API / モバイルバックエンド / コスト優先なら HTTP API。
誤り2: Standard Workflow と Express Workflow の取り違え
Standard を選んだ後に実行頻度が増えてコストが爆発するケースと、Express を選んだ後に 90日後の監査要件で実行履歴が消えているケースが頻発する。選択基準: 監査・実行履歴保持が必要 → Standard。高頻度・短時間・コスト優先 → Express。
誤り3: Lambda Authorizer のキャッシュ設定漏れ
Lambda Authorizer はデフォルトでキャッシュ TTL = 300秒だが、設定を 0 にすると全リクエストで Authorizer Lambda が呼び出され、コストとレイテンシが増大する。本番では TTL を適切に設定し、AuthorizerResultTtlInSeconds を確認する。
| 項目 | Lambda | API Gateway (HTTP) | API Gateway (REST) | Step Functions (Standard) | Step Functions (Express) |
|---|---|---|---|---|---|
| Cold Start | あり (数ms〜数秒) | なし | なし | なし | なし |
| 最大実行時間 | 15分 | 29秒 (統合) | 29秒 (統合) | 1年 | 5分 |
| 同時実行上限 | アカウント 1,000 (デフォルト) | 10,000 RPS (リージョン) | 10,000 RPS (リージョン) | 制限なし (実行数課金) | 制限なし |
| コストモデル | GB-秒 + リクエスト数 | $1/100万リクエスト | $3.5/100万リクエスト | $0.025/1,000状態遷移 | $0.00001/状態遷移 |
| 実行履歴保持 | CloudWatch Logs | CloudWatch Logs | CloudWatch Logs | 90日間 | CloudWatch Logs のみ |
| 監査対応 | Logs のみ | Access Log | Access Log + X-Ray | 完全な実行履歴 | Logs 設定必須 |
§2まとめ — 3本柱選定チェックリスト
- [ ] Lambda: Memory/Timeout/VPC attachment を本番要件に合わせて設定済み
- [ ] API Gateway: HTTP API vs REST API の選択基準を確認済み
- [ ] API Gateway: 認証方式 (Cognito / Lambda Authorizer / IAM) を決定済み
- [ ] Step Functions: Standard vs Express の選択基準を確認済み
- [ ] Glue層: EventBridge / SQS / SNS のトリガー設計を確認済み
- [ ] 統合パターン: 3本柱の接続フロー (同期/非同期/バッチ) を設計済み
次の §3 では Lambda 本番運用の詳細 — Cold Start 対策・VPC 設計・Provisioned Concurrency・Lambda Insights — を実装レベルで解説する。
3. Lambda 本番運用 ★山場1 — Cold Start × VPC × Provisioned Concurrency × Lambda Insights
3-1. Lambda 関数設定 — Memory / Timeout / Ephemeral Storage
Lambda 関数のコア設定は3つある。Memory (128MB〜10,240MB)、Timeout (1秒〜15分)、Ephemeral Storage (512MB〜10GB) だ。Memory と Timeout はコストとパフォーマンスに直結する重要パラメータであり、デフォルト値のままで本番投入するのは危険だ。
Memory 設定
Lambda の Memory は CPU 能力とも連動している。1,769MB で vCPU 1 コアに相当し、それ以上のメモリを設定すると複数の vCPU が割り当てられる。データ変換・画像処理・機械学習推論など CPU 集約的なワークロードでは、1,769MB 以上を設定することで CPU ボトルネックを解消できる。メモリを増やすことでコストが上がるように思えるが、処理時間の短縮で相殺されるケースが多く、Lambda Power Tuning で最適点を定量的に特定することが推奨される。
Timeout 設定
Timeout のデフォルトは 3 秒だが、外部 API 呼び出しや DB 処理がある関数には短すぎる場合がある。API Gateway 統合の最大タイムアウトは 29 秒 であり、Lambda の Timeout を 29 秒超に設定しても API Gateway 側でタイムアウトする。非同期呼び出し (SQS / EventBridge) では 15 分まで設定可能だ。
Ephemeral Storage (/ tmp)
/tmp ディレクトリのデフォルト容量は 512MB だが、最大 10GB まで拡張できる。大きなファイルを一時的に展開する処理 (機械学習モデルの読み込み等) では適切に設定する。/tmp は実行環境 (Execution Environment) に紐付いており、同じ実行環境が再利用された際に前回の呼び出しからのファイルが残存することがある。
| 設定項目 | デフォルト | 最大値 | 注意点 |
|---|---|---|---|
| Memory | 128 MB | 10,240 MB | CPUと連動。1,769MB = vCPU 1コア |
| Timeout | 3 秒 | 15 分 | API GW統合は29秒上限 |
| Ephemeral Storage | 512 MB | 10 GB | /tmp 残存注意 |
3-2. Cold Start 構造 (Init phase / Invoke phase / Provisioned Concurrency の挙動)
Lambda のコールドスタートは、新しい実行環境 (Execution Environment) を初期化する際に発生する。コールドスタートには2つのフェーズがある。Init phase (実行環境の初期化) と Invoke phase (ハンドラーの実行) だ。
Lambda Invoke ライフサイクル シーケンス
sequenceDiagram
participant Req as リクエスト
participant LambdaSvc as Lambda Service
participant EE as Execution Environment
participant Code as 関数コード
Note over Req,Code: Cold Start (新規EE作成時)
Req->>LambdaSvc: Invoke
LambdaSvc->>EE: Init phase 開始 (EE 初期化)
EE->>EE: OS/ランタイム起動 (数十ms〜数秒)
EE->>Code: 関数コードのダウンロード&解凍
Code->>Code: グローバルスコープ初期化 (import/DB接続等)
Note over EE,Code: VPC 接続時は Hyperplane ENI 割り当てもここで発生
EE->>Code: Invoke phase 開始 (ハンドラー実行)
Code->>Req: レスポンス返却
Note over Req,Code: Warm Start (既存EE再利用時)
Req->>LambdaSvc: Invoke
LambdaSvc->>EE: Invoke phase のみ
EE->>Code: ハンドラー直接実行 (Init phase スキップ)
Code->>Req: レスポンス返却 (低レイテンシ)
Note over Req,Code: Provisioned Concurrency (常時ウォームアップ)
LambdaSvc->>EE: 事前に Init phase 完了済み
Req->>LambdaSvc: Invoke
LambdaSvc->>EE: Invoke phase のみ (コールドスタートなし)
Code->>Req: レスポンス返却 (安定した低レイテンシ)
Init phase では (1) OS/ランタイムの起動、(2) 関数パッケージのダウンロードと展開、(3) グローバルスコープのコード実行 (import / DB 接続初期化 / 設定読み込み) の3段階が発生する。グローバルスコープの初期化時間が長いほどコールドスタートのレイテンシが増大するため、不要な初期化をハンドラー内に移動することで改善できる。
3-3. Cold Start 対策3パターン

パターン1: Provisioned Concurrency
最も確実な対策。指定した同時実行数の実行環境を常時初期化済み状態で維持する。Application Auto Scaling と組み合わせてリクエストパターンに合わせた自動スケーリングも可能だ。コストは Provisioned Concurrency の設定数に比例して発生するため、Traffic pattern に合わせたスケジュール設定が重要になる。
resource "aws_lambda_provisioned_concurrency_config" "main" {
function_name = aws_lambda_function.main.function_name
qualifier = aws_lambda_alias.main.name
provisioned_concurrent_executions = 5
}
resource "aws_appautoscaling_target" "lambda_pc" {
max_capacity = 50
min_capacity = 5
resource_id = "function:${aws_lambda_function.main.function_name}:${aws_lambda_alias.main.name}"
scalable_dimension = "lambda:function:ProvisionedConcurrency"
service_namespace = "lambda"
}
パターン2: SnapStart (Java / Python / .NET)
SnapStart は Init phase 完了後のスナップショットを保存し、以降のコールドスタートでスナップショットから復元することで Init time を大幅短縮する機能だ。Java 11 以降 / Python 3.12 / .NET 8 で利用可能。Provisioned Concurrency とは異なり常時課金が発生しない点がコスト優位性だ。SnapStart の詳細実装は Lambda SnapStart 本番運用 deep-dive 記事を参照。
パターン3: Container Image 最適化
Lambda Container Image を使用する場合、イメージサイズが大きいと Init phase のダウンロード時間が増加する。マルチステージビルドと .dockerignore でイメージを最小化し、コールドスタートを短縮できる。Container Image の詳細は Lambda Container Image 本番運用 deep-dive 記事を参照。
3-4. VPC 接続 — ENI 管理 / Subnet 設計 / Security Group
Lambda を VPC 内リソース (RDS / ElastiCache / MSK 等) に接続する場合、VPC 設定が必要となる。2019 年以降、AWS は Hyperplane ENI (Elastic Network Interface) を使った共有 ENI モデルに移行し、以前の問題だった ENI 割り当て遅延と枯渇リスクが大幅に改善された。
Hyperplane ENI 共有モデル
Hyperplane ENI は同じ VPC + Subnet + Security Group 組み合わせで複数の Lambda 実行環境が ENI を共有する仕組みだ。VPC アカウントレベルで ENI 上限 (デフォルト 5,000) は引き続き存在するため、高同時実行の Lambda 関数は設計段階で ENI 使用量を見積もる必要がある。
Subnet 設計
Lambda を Multi-AZ 設計にするには、複数 AZ の Private Subnet を指定する必要がある。Lambda は指定された Subnet のうち利用可能なものにランダムに配置されるため、最低 2 AZ 以上を指定することが推奨される。Lambda は Internet Gateway に直接アクセスできないため、外部 API 呼び出しには NAT Gateway が必要だ。
Security Group 設計
Lambda 用 Security Group は Inbound ルールを空にし、Outbound のみを必要なポートに絞る。RDS への接続は RDS の Security Group で Lambda の Security Group ID を Inbound ソースとして許可する「Security Group 参照」方式が推奨される。
resource "aws_security_group" "lambda" {
name= "lambda-production"
vpc_id = var.vpc_id
egress {
from_port= 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "lambda-production" }
}
3-5. IAM Role 最小特権
Function Execution Role
Lambda 関数には必ず専用の IAM Execution Role を割り当てる。複数の関数間での Role 共有は避け、各関数に必要最小限の権限のみを付与する。基本として AWSLambdaBasicExecutionRole (CloudWatch Logs 書き込み) または VPC 接続時は AWSLambdaVPCAccessExecutionRole を Managed Policy として付与する。
Resource Policy (Function Policy)
Lambda Resource Policy を使うと、API Gateway や EventBridge など別のサービスから Lambda を呼び出す許可を関数単位で管理できる。Terraform では aws_lambda_permission で明示的に定義する必要がある。
resource "aws_iam_role" "lambda_exec" {
name = "lambda-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "vpc_access" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}
resource "aws_lambda_permission" "api_gateway" {
statement_id = "AllowAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.main.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.main.execution_arn}/*/*"
}
3-6. Memory Tuning + Lambda Insights
Lambda Power Tuning
Lambda のコスト × パフォーマンス最適化には AWS Lambda Power Tuning (Step Functions ベースの OSS ツール) が有効だ。指定した Memory 設定の組み合わせ (128MB〜10,240MB) で実関数を複数回実行し、各設定のコストと実行時間をグラフ化してくれる。「コスト最小」「速度最大」「バランス」の3つの最適化軸で推奨値を提示するため、定量的な根拠をもとに Memory を設定できる。
Lambda Insights
Lambda Insights は CloudWatch Lambda Insights Extension を Lambda Layer として追加するだけで、CPU / Memory / Network / Disk I/O のメトリクスを自動収集する。通常の CloudWatch Metrics では取得できないメモリ使用率やイニシャライズ時間の分布を可視化できる。コールドスタートの頻度と init_duration (Init phase 所要時間) の分布を CloudWatch Alarm で監視することで、コールドスタート起因の遅延を早期検知できる。
3-7. Terraform 例: Lambda 本番構成
resource "aws_lambda_function" "main" {
function_name = "myapp-production"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "python3.12"
timeout = 29
memory_size= 512
filename= data.archive_file.lambda.output_path
source_code_hash = data.archive_file.lambda.output_base64sha256
vpc_config {
subnet_ids= var.private_subnet_ids
security_group_ids = [aws_security_group.lambda.id]
}
environment {
variables = {
DB_SECRET_ARN = aws_secretsmanager_secret.db.arn
ENVIRONMENT= "production"
}
}
layers = [
aws_lambda_layer_version.powertools.arn,
]
ephemeral_storage {
size = 512
}
tracing_config {
mode = "Active"
}
tags = { Environment = "production" }
}
resource "aws_lambda_alias" "main" {
name = "production"
function_name = aws_lambda_function.main.function_name
function_version = aws_lambda_function.main.version
}
resource "aws_lambda_provisioned_concurrency_config" "production" {
function_name = aws_lambda_function.main.function_name
qualifier = aws_lambda_alias.main.name
provisioned_concurrent_executions = 5
}
deep-dive 記事クロスリンク
Lambda 関連のより深い実装パターンは以下の deep-dive 記事を参照:
- Container Image: Lambda Container Image 本番運用 — マルチステージビルド / ECR 連携 / コールドスタート最適化
- Powertools + Layers: Lambda Powertools+Layers 本番運用 — 構造化ログ / X-Ray トレーシング / カスタムメトリクス
- SnapStart: Lambda SnapStart 本番運用 — Java/Python SnapStart 設定 / Before/After Snapshot hooks
VPC 接続 Lambda のコールドスタート時に ENI 初期化が発生し、p99 レイテンシが 8 秒超に跳ね上がった遅延事故が多発する。API Gateway の統合タイムアウト上限は 29 秒であるため、8 秒超のコールドスタートに通常のハンドラー処理時間が加算されると 29 秒制限に接触するリスクが生じる。
- 発生条件: VPC 接続 + コールドスタート頻発 (夜間バッチ後のウォームアップ切れ / 急激なトラフィック増加)
- 対策1: Provisioned Concurrency を設定してコールドスタートを排除。スケジュールベースの Auto Scaling で夜間縮退・昼間スケールアウトを自動化
- 対策2: Lambda Insights の
init_durationメトリクスを CloudWatch Alarm で監視し、Init time 急増を早期検知 - 対策3: グローバルスコープのコードを最小化する (import の遅延評価化 / DB 接続プールサイズ削減)
古い設計パターン (2019年以前の推奨) に基づいて構築された Lambda 環境で、同時実行数の急増時に ENI 枯渇が発生し、関数が起動できない障害が報告されている。Hyperplane ENI モデルへの移行後もアカウントレベルの ENI 上限 (デフォルト 5,000) は存在するため、大規模並列実行では設計段階での見積もりが不可欠だ。
- 発生条件: Lambda Reserved Concurrency を高く設定 + 複数関数が異なる Subnet/SG 組み合わせを多数使用 + アカウント ENI 上限に接近
- 対策1: VPC 設計で Lambda 専用 Subnet (/24 以上) を確保し、他リソースとの ENI 競合を避ける
- 対策2: CloudWatch メトリクス
NetworkInterfaceCountを監視し、ENI 使用量がアカウント上限の 80% を超えたらアラームを発報する - 対策3: Service Quotas で ENI 上限引き上げを申請し、急激なトラフィック成長に備える
4. API Gateway 本番運用 ★山場2 — HTTP API vs REST × 認証3方式 × Throttling × CORS × Custom Domain
4-1. HTTP API vs REST API — 選定軸と本番判断基準
API Gateway は HTTP API と REST API の 2 つのエンドポイントタイプを提供する。機能セット・コスト・レイテンシが大きく異なるため、ワークロードに応じて正確に選定する必要がある。
| 比較軸 | HTTP API | REST API |
|---|---|---|
| コスト | $1.00/100万リクエスト | $3.50/100万リクエスト (アジア太平洋) |
| レイテンシ | 低い (約 30% 高速) | やや高い |
| 認証方式 | JWT / Lambda Authorizer / IAM Auth | Cognito / Lambda Authorizer / IAM / API Key |
| Custom Authorizer Cache | あり | あり (より細かい TTL 制御) |
| Usage Plan / API Key | なし | あり (マルチテナント Throttle 管理) |
| Canary Deployment | あり | あり |
| Stage Variables | なし | あり |
| Request Validation | なし | あり (リクエストボディ/パラメータ) |
| Private API | なし | あり (VPC Endpoint 経由) |
| AWS X-Ray Tracing | あり | あり |
| Access Logging | あり | あり |
選定の原則:
– HTTP API を選ぶ場合: シンプルな REST 用途・低コスト重視・JWT ベースの認証で十分・SPA / モバイルバックエンド
– REST API を選ぶ場合: マルチテナント Usage Plan 管理が必要・Request Validation が必要・既存の Stage Variables を活用・Private API が必要
4-2. HTTP API 認証3方式
JWT 認証 (推奨: SPA × モバイル)
HTTP API の JWT Authorizer は、Amazon Cognito・Auth0・Okta 等の JWT を発行する IdP と直接統合できる。API Gateway が JWT の署名検証 (JWKS エンドポイント経由) と claims 検証を行うため、Lambda Authorizer が不要でコストとレイテンシが削減される。
resource "aws_apigatewayv2_api" "http_api" {
name = "prod-http-api"
protocol_type = "HTTP"
cors_configuration {
allow_origins = ["https://app.example.com"]
allow_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
allow_headers = ["Content-Type", "Authorization"]
max_age = 300
}
}
resource "aws_apigatewayv2_authorizer" "jwt" {
api_id = aws_apigatewayv2_api.http_api.id
authorizer_type = "JWT"
identity_sources = ["$request.header.Authorization"]
name = "cognito-jwt"
jwt_configuration {
audience = [aws_cognito_user_pool_client.app.id]
issuer= "https://cognito-idp.${var.region}.amazonaws.com/${aws_cognito_user_pool.main.id}"
}
}
resource "aws_apigatewayv2_route" "api_route" {
api_id = aws_apigatewayv2_api.http_api.id
route_key = "GET /items"
authorization_type = "JWT"
authorizer_id= aws_apigatewayv2_authorizer.jwt.id
target = "integrations/${aws_apigatewayv2_integration.lambda.id}"
}
Lambda Authorizer (カスタム認証ロジック)
JWT 以外の認証スキーム (独自トークン・APIキー・mTLS) や、DB 照合・外部 IdP コール等の複雑なロジックが必要な場合に使用する。HTTP API の Lambda Authorizer は REQUEST type のみをサポートし、レスポンスとして シンプルな isAuthorized boolean を返すモードと IAM ポリシー を返すモードが選択できる。
IAM Auth (サービス間通信)
AWS サービス間 (他 Lambda・ECS タスク・EventBridge Pipes 等) での API 呼び出しには IAM Auth が最適だ。Signature Version 4 で署名したリクエストを API Gateway が検証する。追加の Authorizer Lambda が不要でレイテンシが最小化される。
4-3. REST API 認証設計 — Cognito / Lambda Authorizer / IAM / API Key + Usage Plan
Cognito User Pool Authorizer
REST API では Cognito User Pool をネイティブに Authorizer として設定できる。Cognito が発行した Access Token または ID Token を Authorization ヘッダで受け取り、API Gateway が署名検証と有効期限確認を行う。
API Key + Usage Plan — マルチテナント Throttle 管理
REST API 固有の機能として、テナント単位の API Key + Usage Plan による Throttle 管理がある。Account-level 制限 (10,000 rps) とは独立したテナント別 Rate/Burst 制限を設定でき、特定テナントの大量リクエストが他テナントに影響しない多テナント設計の基盤となる。
resource "aws_api_gateway_rest_api" "rest_api" {
name = "prod-rest-api"
endpoint_configuration {
types = ["REGIONAL"]
}
}
resource "aws_api_gateway_usage_plan" "tenant_standard" {
name = "tenant-standard"
throttle_settings {
rate_limit = 100
burst_limit = 200
}
quota_settings {
limit = 50000
period = "DAY"
}
api_stages {
api_id = aws_api_gateway_rest_api.rest_api.id
stage = aws_api_gateway_stage.prod.stage_name
throttle {
path = "/items/GET"
rate_limit = 50
burst_limit = 100
}
}
}
resource "aws_api_gateway_api_key" "tenant_key" {
name = "tenant-a-key"
}
resource "aws_api_gateway_usage_plan_key" "tenant_plan_key" {
key_id = aws_api_gateway_api_key.tenant_key.id
key_type= "API_KEY"
usage_plan_id = aws_api_gateway_usage_plan.tenant_standard.id
}
4-4. Custom Authorizer 設計 — TOKEN vs REQUEST / Cache TTL
REST API の Lambda Authorizer には TOKEN type と REQUEST type の 2 種類がある。
| 項目 | TOKEN type | REQUEST type |
|---|---|---|
| 入力 | Authorization ヘッダの値のみ | ヘッダ / クエリパラメータ / パス / ステージ変数すべて |
| 用途 | Bearer Token / JWT 検証 | 複数パラメータ組み合わせによる認証 |
| Cache Key | Token 値 | 指定したパラメータ組み合わせ |
Cache TTL の設計指針
Lambda Authorizer の応答キャッシュは TTL 0〜3600 秒の範囲で設定できる。TTL を長くするとオーソライザー Lambda の呼び出し回数が減りコストとレイテンシが削減されるが、トークン失効後もキャッシュが有効な間はアクセスが許可される。セキュリティ要件に合わせて TTL を設計する。
resource "aws_api_gateway_authorizer" "lambda_auth" {
name = "custom-authorizer"
rest_api_id = aws_api_gateway_rest_api.rest_api.id
authorizer_uri = aws_lambda_function.authorizer.invoke_arn
authorizer_credentials = aws_iam_role.authorizer_invocation.arn
type = "TOKEN"
identity_source= "method.request.header.Authorization"
authorizer_result_ttl_in_seconds = 300
}
Lambda Authorizer の実装パターンについては API Gateway Lambda Authorizer Production 完全ガイド で詳しく解説している。
4-5. Throttling — Account-level / Stage-level / Method-level / Usage Plan
Throttling の階層構造
API Gateway の Throttling は 4 つの階層で制御される。上位の制限が下位の設定より優先される。
| 階層 | 対象 | デフォルト | 変更方法 |
|---|---|---|---|
| Account-level | アカウント全体 | 10,000 rps / 5,000 burst | サービスクォータ申請 |
| Stage-level | Stage 単位 | Account-level を共有 | Terraform aws_api_gateway_stage |
| Method-level | Route + Method 単位 | Stage-level を共有 | Terraform aws_api_gateway_method_settings |
| Usage Plan | API Key 単位 | 独立設定 | Terraform aws_api_gateway_usage_plan |
Rate vs Burst の違い
- Rate limit: 秒間の持続スループット上限。長期的なリクエスト流量を制限する
- Burst limit: Token Bucket アルゴリズムによる短期スパイク許容量。瞬間的なアクセス集中を吸収する
resource "aws_api_gateway_stage" "prod" {
rest_api_id= aws_api_gateway_rest_api.rest_api.id
stage_name = "prod"
deployment_id = aws_api_gateway_deployment.main.id
default_route_settings {
throttling_rate_limit = 1000
throttling_burst_limit = 2000
}
}
resource "aws_api_gateway_method_settings" "per_method" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
stage_name = aws_api_gateway_stage.prod.stage_name
method_path = "items/GET"
settings {
throttling_rate_limit = 500
throttling_burst_limit = 1000
logging_level = "INFO"
data_trace_enabled = false
metrics_enabled = true
}
}
4-6. CORS 設定 + Custom Domain
CORS Preflight の仕組み
ブラウザが cross-origin リクエストを送る前に OPTIONS メソッドの Preflight リクエストを API Gateway に送信する。API Gateway が適切な Access-Control-Allow-* レスポンスヘッダを返さないと、ブラウザがメインリクエストをブロックする。
HTTP API は cors_configuration ブロックで CORS を一括設定できるが、REST API では各リソースに OPTIONS メソッドを個別に定義し、Integration Response でヘッダを設定する必要がある。
Custom Domain — Edge-optimized / Regional
| タイプ | CDN 利用 | 推奨用途 |
|---|---|---|
| Edge-optimized | CloudFront (自動) | グローバルアクセス分散 |
| Regional | なし (同一リージョン) | Single-Region・VPC 内アクセス |
| Private | VPC Endpoint のみ | 内部 API |
resource "aws_api_gateway_domain_name" "custom" {
domain_name = "api.example.com"
regional_certificate_arn = aws_acm_certificate.api.arn
endpoint_configuration {
types = ["REGIONAL"]
}
}
resource "aws_api_gateway_base_path_mapping" "v1" {
api_id= aws_api_gateway_rest_api.rest_api.id
stage_name = aws_api_gateway_stage.prod.stage_name
domain_name = aws_api_gateway_domain_name.custom.domain_name
base_path= "v1"
}

あるマルチテナント SaaS で API Gateway REST API に Usage Plan を設定していなかった場合、特定テナントが 1 万 rps を超えるリクエストを送信した際に Account-level Throttle (10,000 rps) に抵触し、同一アカウントの他テナント向け API も全て
429 Too Many Requests を返し始めた。1 テナントの大量リクエストが全テナントのサービス停止を引き起こす事態となった。根本原因: テナントごとの API Key + Usage Plan が未設定で、全テナントが同一 Account-level 制限を共有していた。
対策: テナント単位で API Key + Usage Plan を発行し、Rate/Burst を個別設定する。各テナントの Usage Plan の Rate 合計が Account-level 制限の 80% を超えないよう設計し、余剰をバッファとして確保する。CloudWatch メトリクス 4XXError および Count をテナント別に分解し、特定テナントの Throttle 発生をアラートで早期検知する。
REST API に GET / POST のみを定義し OPTIONS を省略したところ、SPA からのリクエストが全て
CORS policy エラーでブロックされた。ブラウザは Content-Type: application/json を含む non-simple リクエストに対して事前に OPTIONS Preflight を送るが、API Gateway が 403 を返し CORS ヘッダが付かなかったためだ。対策: REST API では各リソースに OPTIONS メソッドを定義し、統合タイプを MOCK にして Access-Control-Allow-Origin / Access-Control-Allow-Methods / Access-Control-Allow-Headers の 3 ヘッダを返す。HTTP API は cors_configuration ブロックで一括設定できるため、新規構築では HTTP API を選択することで CORS 設定ミスを防止できる。
既存 API Gateway deep-dive 記事へのクロスリンク
本節では API Gateway の認証・Throttling・CORS・Custom Domain の本番設計を解説した。Lambda Authorizer の詳細実装については専門記事で扱っている。
- API Gateway Lambda Authorizer Production 完全ガイド — TOKEN type / REQUEST type 実装・Cache 設計・IAM Policy 生成パターンを詳解。Custom Authorizer の本番運用はこちら。
5. Step Functions 本番運用 ★山場3 — Standard vs Express × Distributed Map × Callback Pattern × Error Handling × SDK Direct
Step Functions は ASL (Amazon States Language) ベースのサーバーレスワークフローオーケストレーターです。複数の AWS サービスを宣言的に連携させ、Retry/Catch/Parallel/Map を組み合わせた本番品質のワークフローを実現します。
5-1. Standard vs Express — 選定軸
| 項目 | Standard | Express |
|---|---|---|
| 最大実行時間 | 1 年 | 5 分 |
| コスト | 状態遷移数課金 | 継続時間 × リクエスト数 |
| 実行履歴 | Step Functions コンソールに全状態保存 | CloudWatch Logs のみ |
| 一貫性 | Exactly-once | At-least-once |
| 同期実行 | StartSyncExecution (2分上限) | StartSyncExecution (2分上限) |
| 適用場面 | 人手承認 / 長時間バッチ / 課金処理 | API Gateway バックエンド / 高頻度短時間 |
選定基準:
– 実行時間 5 分以内 かつ 高頻度 (1,000+ 回/秒) → Express
– 人手承認 / waitForTaskToken / 長時間実行 → Standard
– Exactly-once 保証が必要 (DB 更新 / 決済処理) → Standard
– API Gateway バックエンドで同期レスポンスが必要 → Express
5-2. Distributed Map — 大規模並列バッチ
Distributed Map は通常 Map state の拡張版で、最大 10,000 並列実行が可能です。S3 上の CSV/JSON ファイルをストリーミングで直接読み込み、数百万件規模のバッチ処理に対応します。
| 項目 | Map state | Distributed Map |
|---|---|---|
| 最大並列数 | 40 | 10,000 |
| データソース | State input (メモリ) | S3 / JSON 配列 |
| Child execution | Standard 履歴に含まれる | Standard から分離した Child |
| 適用スケール | 数百件以内 | 数万〜数百万件 |
{
"ProcessBatch": {
"Type": "Map",
"ItemReader": {
"Resource": "arn:aws:states:::s3:getObject",
"ReaderConfig": {
"InputType": "CSV",
"CSVHeaderLocation": "FIRST_ROW"
},
"Parameters": {
"Bucket.$": "$.bucket",
"Key.$": "$.key"
}
},
"MaxConcurrency": 1000,
"ToleratedFailurePercentage": 5,
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "EXPRESS"
},
"StartAt": "Process",
"States": {
"Process": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${LambdaArn}",
"Payload.$": "$"
},
"End": true
}
}
},
"End": true
}
}
ExecutionType: EXPRESS により Child execution を Standard の 25K 状態履歴制限から分離します。ToleratedFailurePercentage: 5 でアイテムの 5% 失敗を許容し全体処理を継続させます。
5-3. Callback Pattern — waitForTaskToken
Callback Pattern は Step Functions が外部システムや人手処理の完了を待機するパターンです。waitForTaskToken 接尾辞リソースにより Task Token を Lambda/SQS へ渡し、処理完了後に SendTaskSuccess / SendTaskFailure を呼び出して状態機械を再開させます。
適用場面:
– 人手承認フロー (Slack 通知 → 承認ボタン → SendTaskSuccess)
– 外部 API の非同期コールバック待機
– SaaS Webhook 受信待機
sequenceDiagram
participant SF as Step Functions
participant Lambda as Notification Lambda
participant Approver as Human Approver
participant API as Callback API
SF->>Lambda: Invoke with taskToken
Lambda->>Approver: Slack 通知 (taskToken 埋め込み)
Note over SF: waitForTaskToken 待機中...
Approver->>API: 承認ボタン押下
API->>SF: SendTaskSuccess(taskToken, output)
SF->>SF: 次状態へ遷移
ASL 定義 (waitForTaskToken):
{
"WaitForApproval": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "${NotificationLambdaArn}",
"Payload": {
"taskToken.$": "$$.Task.Token",
"requestId.$": "$.requestId"
}
},
"HeartbeatSeconds": 86400,
"Catch": [
{
"ErrorEquals": ["States.HeartbeatTimeout"],
"Next": "ApprovalTimeout",
"ResultPath": "$.error"
}
],
"Next": "ProcessApproval"
}
}
HeartbeatSeconds: 86400 (24時間) を設定し、承認が来ない場合は HeartbeatTimeout として Catch で補足します。Task Token は $$.Task.Token (Context Object) から取得します。
5-4. Error Handling — Retry / Catch / 指数バックオフ
Step Functions の Error Handling は ASL レベルで宣言します。Lambda の一時的な失敗には Retry、恒久的な失敗には Catch を使います。
{
"CallLambda": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${LambdaArn}",
"Payload.$": "$"
},
"Retry": [
{
"ErrorEquals": ["Lambda.ServiceException", "Lambda.AWSLambdaException"],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2.0
}
],
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Next": "HandleError",
"ResultPath": "$.error"
}
],
"Next": "Done"
}
}
BackoffRate: 2.0: 指数バックオフ。初回 2 秒 → 4 秒 → 8 秒ResultPath: "$.error": Catch 後のエラー情報を入力 JSON にマージして次状態へ渡す- DLQ パターン: Catch → SQS SendMessage (SDK Direct) → Lambda で非同期デッドレター処理
5-5. SDK Direct Integration — Lambda不要で AWS API を直接呼び出し
SDK Direct Integration は Lambda を介さずに 200 以上の AWS API を ASL から直接呼び出せる機能です。Lambda 実行コスト・コールドスタート・ボイラープレートを排除できます。
| リソース | 用途 |
|---|---|
arn:aws:states:::dynamodb:putItem | 結果の永続化 |
arn:aws:states:::sqs:sendMessage | キューイング / DLQ |
arn:aws:states:::sns:publish | 通知送信 |
arn:aws:states:::ecs:runTask.sync | コンテナバッチ実行 |
arn:aws:states:::bedrock:invokeModel | LLM 推論 |
{
"PersistResult": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:putItem",
"Parameters": {
"TableName": "${TableName}",
"Item": {
"pk": {"S.$": "$.orderId"},
"status": {"S": "COMPLETED"},
"updatedAt": {"S.$": "$$.Execution.StartTime"}
}
},
"ResultPath": null,
"Next": "Done"
}
}
ResultPath: null は SDK 戻り値を破棄し、入力 JSON をそのまま次状態へ渡す慣用パターンです。
5-6. ASL 設計 + I/O Filter
State 種別:
| State | 用途 |
|---|---|
| Task | AWS サービス呼び出し (Lambda / SDK Direct) |
| Choice | 条件分岐 |
| Wait | 固定時間 / タイムスタンプ待機 |
| Parallel | 並列実行ブランチ |
| Map | 配列処理 (通常 / Distributed) |
| Pass | 入力変換・定数注入 |
I/O Filter パイプライン: 入力 → InputPath → Parameters → Task → ResultSelector → ResultPath → OutputPath → 次状態
State payload 上限は 256KB です。大容量データは S3 に書き出し、Key だけをポインタとして渡す External Payload Pattern を採用してください。
5-7. deep-dive 記事クロスリンク
Step Functions の各機能はそれぞれ独立した deep-dive シリーズで詳細解説しています。
- Standard vs Express 選定: Step Functions Express vs Standard Production — 詳細比較・移行ガイド
- 大規模並列: Step Functions Distributed Map Production — S3 ソース設計・Concurrency 制御
- 人手承認: Step Functions Callback waitForTaskToken — Slack 連携・Webhook 実装詳細
- 障害対応: Step Functions Error Handling — Retry 設計・DLQ 連携・部分失敗ハンドリング
- コスト削減: Step Functions SDK Direct Integration Production — 200+ API 活用レシピ
5-8. Terraform 実装例

# Standard ステートマシン (人手承認 + Callback + Error Handling)
resource "aws_sfn_state_machine" "approval" {
name = "${var.project}-approval"
role_arn = aws_iam_role.sfn.arn
type = "STANDARD"
definition = jsonencode({
Comment = "Standard: waitForTaskToken Callback + Error Handling"
StartAt = "WaitForApproval"
States = {
WaitForApproval = {
Type = "Task"
Resource = "arn:aws:states:::lambda:invoke.waitForTaskToken"
Parameters = {
FunctionName = aws_lambda_function.notifier.arn
Payload = {
"taskToken.$" = "$$.Task.Token"
"requestId.$" = "$.requestId"
}
}
HeartbeatSeconds = 86400
Retry = [{
ErrorEquals = ["Lambda.ServiceException"]
IntervalSeconds = 2
MaxAttempts = 3
BackoffRate = 2.0
}]
Catch = [{
ErrorEquals = ["States.ALL"]
Next = "HandleError"
ResultPath = "$.error"
}]
Next = "Done"
}
Done = { Type = "Succeed" }
HandleError = { Type = "Fail", Error = "WorkflowFailed" }
}
})
logging_configuration {
log_destination = "${aws_cloudwatch_log_group.sfn.arn}:*"
include_execution_data = true
level= "ERROR"
}
tags = var.common_tags
}
# Distributed Map ステートマシン (S3 CSV 大規模並列バッチ)
resource "aws_sfn_state_machine" "batch" {
name = "${var.project}-batch"
role_arn = aws_iam_role.sfn.arn
type = "STANDARD"
definition = jsonencode({
Comment = "Distributed Map: S3 CSV parallel batch"
StartAt = "ProcessBatch"
States = {
ProcessBatch = {
Type = "Map"
ItemReader = {
Resource = "arn:aws:states:::s3:getObject"
ReaderConfig = {
InputType= "CSV"
CSVHeaderLocation = "FIRST_ROW"
}
Parameters = {
"Bucket.$" = "$.bucket"
"Key.$" = "$.key"
}
}
MaxConcurrency = 1000
ToleratedFailurePercentage = 5
ItemProcessor = {
ProcessorConfig = {
Mode = "DISTRIBUTED"
ExecutionType = "EXPRESS"
}
StartAt = "Process"
States = {
Process = {
Type = "Task"
Resource = "arn:aws:states:::lambda:invoke"
Parameters = {
FunctionName = aws_lambda_function.processor.arn
"Payload.$" = "$"
}
End = true
}
}
}
End = true
}
}
})
tags = var.common_tags
}
あるバッチ処理で通常 Map state を使用して 50,000 件を並列処理した結果、Standard ステートマシンの 1 Execution あたり 25,000 状態遷移上限を超過し、実行が強制終了されました。再試行してもすべて同じ上限で失敗するため、バッチ処理が完全停止しました。Distributed Map + Express Child execution への書き直しで根本解決しました。
対処パターン:
1. 数百件を超えるアイテムを並列処理する設計は最初から Distributed Map を採用する
2. ExecutionType: EXPRESS で Child execution を Standard 履歴から分離し、25K 制限を回避する
3. ToleratedFailurePercentage を設定し、一部アイテム失敗時も全体処理が継続されるよう設計する
Express ステートマシンで実装した推論パイプラインが、本番データ量の増加に伴い実行時間が 5 分を超過し始め、実行が自動終了されるようになりました。Express は 5 分が絶対上限のため設定変更での対処は不可能で、ステートマシンを Standard に作り直す対応が必要になりました。
対処パターン:
1. 実行時間が 5 分を超える可能性があるワークフローは設計時点で Standard を選択する
2. Express を使用する場合は Lambda Timeout の合計 + Step Functions オーバーヘッドが 4 分以内に収まることを試算する
3. CloudWatch Logs Insights で Express 実行時間を定期監視し、4 分超でアラートを設定して移行判断の余地を持つ
6. 詰まりポイント7選 — Cold Start遅延 / VPC ENI / Lambda timeout / APIGW throttle / SF状態爆発 / IAM hell / Cost runaway
詰まり1: Cold Start p99 遅延 — VPC ENI 初期化 + 大型 Container Image が重なると 8 秒超
対処パターン:
1. Provisioned Concurrency: ウォームアップ済みインスタンスを常時確保し、コールドスタートを排除する。Auto Scaling Schedule と組み合わせてコストを抑制する
2. SnapStart (Java/Python/.NET): 初期化フェーズのスナップショットを取得し、再利用することで JVM 起動コストを大幅削減
3. Container Image を最小化 (multi-stage build / Lambda-specific base image 使用)
4. VPC 不要な処理は VPC 外 Lambda に分離する
# Provisioned Concurrency + Auto Scaling スケジュール
resource "aws_lambda_provisioned_concurrency_config" "api" {
function_name= aws_lambda_function.api.function_name
qualifier = aws_lambda_alias.live.name
provisioned_concurrent_executions = 10
}
resource "aws_appautoscaling_target" "lambda_pc" {
max_capacity = 50
min_capacity = 5
resource_id = "function:${aws_lambda_function.api.function_name}:${aws_lambda_alias.live.name}"
scalable_dimension = "lambda:function:ProvisionedConcurrency"
service_namespace = "lambda"
}
resource "aws_appautoscaling_scheduled_action" "scale_up" {
name= "scale-up-business-hours"
service_namespace = "lambda"
resource_id = aws_appautoscaling_target.lambda_pc.resource_id
scalable_dimension = aws_appautoscaling_target.lambda_pc.scalable_dimension
schedule = "cron(0 8 * * ? *)"
scalable_target_action {
min_capacity = 20
max_capacity = 50
}
}
詰まり2: VPC ENI 枯渇 — 旧設計で同時実行ごとに ENI 1個消費
対処パターン:
1. Subnet の利用可能 IP 数を確認する (/24 以上が推奨。Lambda は Hyperplane 共有でも Subnet IP を消費する)
2. 複数 AZ の Subnet を指定して VPC Config を設定することで、ENI リソースを分散する
3. Lambda 関数の VPC Config を更新すると Hyperplane ENI 共有が自動適用される
4. CloudWatch Metrics の ENILimit / VPCResourceCheckFailure を監視してアラームを設定する
resource "aws_lambda_function" "api" {
function_name = "my-api-handler"
runtime = "python3.12"
handler = "app.handler"
filename= "lambda.zip"
role = aws_iam_role.lambda_exec.arn
# ✅ 複数AZ の Subnet を指定 (Hyperplane ENI 共有 + IP 分散)
vpc_config {
subnet_ids= [
aws_subnet.private_a.id,
aws_subnet.private_b.id,
aws_subnet.private_c.id,
]
security_group_ids = [aws_security_group.lambda.id]
}
memory_size = 512
timeout = 30
}
詰まり3: Lambda Timeout vs API Gateway 29秒制限の衝突
対処パターン:
1. 非同期パターン: API Gateway → Lambda (SQS/EventBridge キューへエンキュー) → 202 Accepted を即返却。処理は別 Lambda が非同期で実行
2. Step Functions オフロード: 長時間処理を Step Functions State Machine に委譲し、実行 ARN を返却。クライアントはポーリングまたは Callback で結果を受け取る
3. WebSocket API を使用してリアルタイム結果通知を実現する
# SQS 非同期処理パターン: API Lambda は即エンキューして 202 返却
resource "aws_sqs_queue" "job_queue" {
name = "job-queue"
visibility_timeout_seconds = 300
message_retention_seconds = 86400
}
resource "aws_lambda_event_source_mapping" "worker" {
event_source_arn = aws_sqs_queue.job_queue.arn
function_name = aws_lambda_function.worker.arn
batch_size = 1
function_response_types = ["ReportBatchItemFailures"]
}
詰まり4: API Gateway Throttling — Account-level 制限で全テナントが被害を受ける
対処パターン:
1. Stage-level Throttle で API 全体の上限を設定する
2. Method-level Throttle で重要エンドポイントに細かい制限を設ける
3. Usage Plan + API Key でテナント別に Throttle 枠を分離し、1 テナントの暴走が他テナントに波及しないようにする
# API Gateway Usage Plan でテナント別スロットリング
resource "aws_api_gateway_usage_plan" "standard" {
name = "standard-plan"
description = "Standard tier: 100 rps / 10000 daily"
api_stages {
api_id = aws_api_gateway_rest_api.app.id
stage = aws_api_gateway_stage.prod.stage_name
}
throttle_settings {
rate_limit = 100# rps per API Key
burst_limit = 200
}
quota_settings {
limit = 10000
period = "DAY"
}
}
resource "aws_api_gateway_api_key" "tenant_a" {
name = "tenant-a-key"
}
resource "aws_api_gateway_usage_plan_key" "tenant_a" {
key_id = aws_api_gateway_api_key.tenant_a.id
key_type= "API_KEY"
usage_plan_id = aws_api_gateway_usage_plan.standard.id
}
詰まり5: Step Functions 状態爆発 — Map state で履歴 25K 制限に抵触
対処パターン:
1. Distributed Map に移行する — 子 Workflow を別の State Machine Execution として起動するため、親の履歴にカウントされない。10,000 並列まで対応し、S3 オブジェクト/JSON 配列を直接ソースとして読み込める
2. バッチサイズを分割して直接 Map state の Iteration 数を 25K 以下に抑える (小規模の場合)
3. Express Workflow を子 State Machine として組み合わせることで、履歴を親から分離できる
{
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "EXPRESS"
},
"StartAt": "ProcessItem",
"States": {
"ProcessItem": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "process-item",
"Payload.$": "$"
},
"End": true
}
}
},
"ItemsPath": "$.items",
"MaxConcurrency": 100,
"ToleratedFailurePercentage": 5
}
詰まり6: IAM Role 設計の複雑化 — Serverless 4 Role を整理する
責務分離設計:
| Role | Trust Principal | 最小権限 |
|——|—————-|———|
| Lambda Function Role | lambda.amazonaws.com | 対象 DynamoDB/S3/SQS への個別 Action |
| Step Functions Role | states.amazonaws.com | Lambda Invoke / SQS Send / SNS Publish 等 |
| API Gateway Role | apigateway.amazonaws.com | CloudWatch Logs への書き込みのみ |
| EventBridge Scheduler Role | scheduler.amazonaws.com | Step Functions StartExecution / Lambda Invoke |
# Step Functions に Lambda 起動権限を付与
resource "aws_iam_role" "sfn_exec" {
name = "sfn-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "states.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "sfn_lambda" {
name = "sfn-invoke-lambda"
role = aws_iam_role.sfn_exec.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect= "Allow"
Action= ["lambda:InvokeFunction"]
Resource = [aws_lambda_function.processor.arn]
},
{
Effect= "Allow"
Action= ["logs:CreateLogGroup", "logs:CreateLogDelivery", "logs:PutLogEvents"]
Resource = "arn:aws:logs:*:*:*"
}
]
})
}
詰まり7: Cost Runaway — Provisioned Concurrency 過剰確保と Standard Workflow 過剰実行
対処パターン:
1. Provisioned Concurrency の Auto Scaling Schedule を設定し、業務時間外は最小値 (2〜5 など) に削減する
2. 高頻度 Workflow (実行時間 5 分以内) は Express Workflow ($1.00 / 100 万実行 + GB 秒) に切り替える
3. CloudWatch Metrics の ProvisionedConcurrencyInvocations / ProvisionedConcurrencySpilloverInvocations を監視して適切な PC 数を調整する
4. Cost Explorer で Lambda / Step Functions のコストを分離タグでトラッキングする
# Provisioned Concurrency: 夜間スケールダウンスケジュール
resource "aws_appautoscaling_scheduled_action" "scale_down" {
name= "scale-down-night"
service_namespace = "lambda"
resource_id = aws_appautoscaling_target.lambda_pc.resource_id
scalable_dimension = aws_appautoscaling_target.lambda_pc.scalable_dimension
schedule = "cron(0 20 * * ? *)"
scalable_target_action {
min_capacity = 2
max_capacity = 5
}
}
# Step Functions Express Workflow: 高頻度処理向け
resource "aws_sfn_state_machine" "express_processor" {
name = "high-frequency-processor"
type = "EXPRESS" # ✅ 高頻度 → Express
role_arn = aws_iam_role.sfn_exec.arn
definition = jsonencode({
Comment = "High-frequency processor (Express)"
StartAt = "Process"
States = {
Process = {
Type = "Task"
Resource = aws_lambda_function.processor.arn
End= true
}
}
})
logging_configuration {
level= "ERROR"
include_execution_data = false
log_destination = "${aws_cloudwatch_log_group.sfn_express.arn}:*"
}
}
7. アンチパターン→正解パターン変換演習 (5件)
演習1: 壊れた Lambda + VPC — Subnet 1個 で ENI 枯渇
Before (アンチパターン):
resource "aws_lambda_function" "api" {
function_name = "my-api"
runtime = "python3.12"
handler = "app.handler"
filename= "lambda.zip"
role = aws_iam_role.lambda_exec.arn
# ❌ Subnet 1個のみ → 1 AZ に ENI が集中 / IP が枯渇すると起動不可
vpc_config {
subnet_ids= [aws_subnet.private_a.id]
security_group_ids = [aws_security_group.lambda.id]
}
}
After (正解パターン):
resource "aws_lambda_function" "api" {
function_name = "my-api"
runtime = "python3.12"
handler = "app.handler"
filename= "lambda.zip"
role = aws_iam_role.lambda_exec.arn
# ✅ 3 AZ の Subnet を指定 — ENI 分散 + AZ 障害に対する耐障害性
vpc_config {
subnet_ids = [
aws_subnet.private_a.id,
aws_subnet.private_b.id,
aws_subnet.private_c.id,
]
security_group_ids = [aws_security_group.lambda.id]
}
memory_size = 512
timeout = 30
# Provisioned Concurrency でコールドスタート排除
publish = true
}
resource "aws_lambda_alias" "live" {
name = "live"
function_name = aws_lambda_function.api.function_name
function_version = aws_lambda_function.api.version
}
resource "aws_lambda_provisioned_concurrency_config" "api" {
function_name = aws_lambda_function.api.function_name
qualifier = aws_lambda_alias.live.name
provisioned_concurrent_executions = 5
}
解説: Lambda VPC 接続では Hyperplane ENI 共有が自動適用されるが、Subnet の利用可能 IP が枯渇するとENI 割り当てに失敗して起動できなくなる。3 AZ の Subnet を指定することで IP アドレス空間を 3 倍に広げ、AZ 障害時の自動切替も確保する。Subnet は /24 以上 (254 IP) を推奨し、他のリソースと IP 空間を共有しないよう Lambda 専用 Subnet を設けるとより安全。
演習2: 壊れた API Gateway — Usage Plan 未設定で Account-level Throttle に抵触
Before (アンチパターン):
resource "aws_api_gateway_rest_api" "app" {
name = "my-app-api"
}
resource "aws_api_gateway_stage" "prod" {
rest_api_id= aws_api_gateway_rest_api.app.id
stage_name = "prod"
deployment_id = aws_api_gateway_deployment.app.id
# ❌ Usage Plan なし → Account-level 10,000 rps を全 API で共有
# ❌ Stage-level Throttle なし → 無制限アクセス可
}
After (正解パターン):
resource "aws_api_gateway_rest_api" "app" {
name = "my-app-api"
}
resource "aws_api_gateway_stage" "prod" {
rest_api_id= aws_api_gateway_rest_api.app.id
stage_name = "prod"
deployment_id = aws_api_gateway_deployment.app.id
# ✅ Stage-level Throttle (全 Method のデフォルト上限)
default_route_settings {
throttling_rate_limit = 500
throttling_burst_limit = 1000
}
}
# ✅ Usage Plan でテナント別 Throttle 管理
resource "aws_api_gateway_usage_plan" "standard" {
name = "standard-plan"
api_stages {
api_id = aws_api_gateway_rest_api.app.id
stage = aws_api_gateway_stage.prod.stage_name
}
throttle_settings {
rate_limit = 100
burst_limit = 200
}
quota_settings {
limit = 50000
period = "DAY"
}
}
resource "aws_api_gateway_api_key" "tenant_a" {
name = "tenant-a"
}
resource "aws_api_gateway_usage_plan_key" "tenant_a" {
key_id = aws_api_gateway_api_key.tenant_a.id
key_type= "API_KEY"
usage_plan_id = aws_api_gateway_usage_plan.standard.id
}
解説: Usage Plan なしで運用すると、悪意ある/バグのある 1 クライアントがリクエストを大量送信してAccount-level Throttle (10,000 rps) を使い切り、同アカウントの全 API が影響を受ける。Usage Plan + API Key でテナントごとにレート制限を設けることで影響範囲を 1 テナントに限定できる。
演習3: 壊れた Step Functions Map state — 25K 履歴制限に抵触
Before (アンチパターン):
{
"Comment": "Process 100k items — WRONG: Standard Map state hits 25K event limit",
"StartAt": "ProcessAll",
"States": {
"ProcessAll": {
"Type": "Map",
"ItemsPath": "$.items",
"MaxConcurrency": 100,
"Iterator": {
"StartAt": "ProcessOne",
"States": {
"ProcessOne": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "process-item",
"Payload.$": "$"
},
"End": true
}
}
},
"End": true
}
}
}
After (正解パターン — Distributed Map):
{
"Comment": "Process 100k items — Distributed Map: child executions are separate",
"StartAt": "ProcessAll",
"States": {
"ProcessAll": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "EXPRESS"
},
"StartAt": "ProcessOne",
"States": {
"ProcessOne": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "process-item",
"Payload.$": "$"
},
"End": true
}
}
},
"ItemsPath": "$.items",
"MaxConcurrency": 1000,
"ToleratedFailurePercentage": 5,
"ResultWriter": {
"Resource": "arn:aws:states:::s3:putObject",
"Parameters": {
"Bucket": "results-bucket",
"Prefix": "results/"
}
},
"End": true
}
}
}
解説: Standard Workflow の inline Map state は各 Iteration のイベント (Start/End 等) が親 Execution の履歴にカウントされる。10 万件では 20 万+ イベントとなり 25K 制限を大幅に超える。Distributed Map は子 Iteration を独立した Express Execution として起動するため、親の履歴消費を最小化しつつ最大 10,000 並列まで処理できる。
演習4: 壊れた Step Functions Callback — waitForTaskToken 未送信で永久待ち
Before (アンチパターン):
{
"Comment": "WRONG: Task Token not sent to external system",
"StartAt": "RequestApproval",
"States": {
"RequestApproval": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "send-approval-request",
"Payload": {
"action": "approve",
"data.$": "$.requestData"
}
},
"HeartbeatSeconds": 3600,
"Next": "ApprovalResult"
},
"ApprovalResult": {
"Type": "Pass",
"End": true
}
}
}
After (正解パターン):
{
"Comment": "CORRECT: waitForTaskToken — Lambda receives token and sends it back",
"StartAt": "RequestApproval",
"States": {
"RequestApproval": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "send-approval-request",
"Payload": {
"taskToken.$": "$$.Task.Token",
"action": "approve",
"data.$": "$.requestData"
}
},
"HeartbeatSeconds": 86400,
"Catch": [{
"ErrorEquals": ["States.HeartbeatTimeout"],
"Next": "ApprovalTimeout"
}],
"Next": "ApprovalResult"
},
"ApprovalResult": {
"Type": "Pass",
"End": true
},
"ApprovalTimeout": {
"Type": "Fail",
"Error": "ApprovalTimedOut",
"Cause": "No response within 24 hours"
}
}
}
import boto3
import json
sfn = boto3.client('stepfunctions')
def handler(event, context):
task_token = event['taskToken']
action = event['action']
request_data = event['data']
# 承認リクエストをメール/Slack等で送信
send_approval_request(
approval_url=f"https://approval.example.com/approve?token={task_token}",
data=request_data
)
# Lambda はここで return — Step Functions は Token の返却を待機
return {"status": "approval_requested"}
def send_approval_request(approval_url, data):
print(f"Approval URL: {approval_url}")
# 承認完了時に呼ばれる別エンドポイント (API Gateway 経由等)
def approve_handler(event, context):
body = json.loads(event.get('body', '{}'))
task_token = body['taskToken']
sfn.send_task_success(
taskToken=task_token,
output=json.dumps({"approved": True, "approver": body.get("approver")})
)
return {"statusCode": 200, "body": "Approved"}
解説: waitForTaskToken リソースを使わずに通常の lambda:invoke を指定すると、Step Functions は Lambda の実行完了をもって次状態に遷移する。外部承認の「結果を待つ」意図が実現されない。$.$.Task.Token で Task Token を Lambda に渡し、Lambda は外部システムへトークン付きの承認 URL を送信。承認後に send_task_success でトークンを返却することで Workflow が再開する。
演習5: 壊れた Lambda IAM Role — AdministratorAccess で最小特権違反
Before (アンチパターン):
# ❌ AdministratorAccess 付与 — 全 AWS リソースを操作可能
resource "aws_iam_role_policy_attachment" "lambda_admin" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
After (正解パターン):
# ✅ 最小特権: DynamoDB + SQS への特定操作のみ許可
resource "aws_iam_role" "lambda_exec" {
name = "lambda-api-exec-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "lambda_basic" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}
resource "aws_iam_role_policy" "lambda_app" {
name = "lambda-app-permissions"
role = aws_iam_role.lambda_exec.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:Query",
]
Resource = [
aws_dynamodb_table.orders.arn,
"${aws_dynamodb_table.orders.arn}/index/*",
]
},
{
Effect= "Allow"
Action= ["sqs:SendMessage", "sqs:GetQueueAttributes"]
Resource = [aws_sqs_queue.job_queue.arn]
}
]
})
}
解説: Lambda Function Role に AdministratorAccess を付与すると、コードのバグや脆弱性を突かれた際にアカウント全体のリソースが侵害される。DynamoDB は対象テーブルの特定 Action のみ、SQS は対象キューのみに絞った最小特権ポリシーを作成する。AWSLambdaVPCAccessExecutionRole (VPC ENI 管理 + CloudWatch Logs 書き込み) は VPC 接続 Lambda では必須のマネージドポリシーとして別途アタッチする。
8. まとめ + Vol2予告 + 落とし穴10選 + 全11軸クロスリンク + 第12軸完結宣言
Vol1 振り返り — 3本柱 × Workload 別選定マトリクス
本記事で習得した Serverless 本番運用 3 本柱の全体像を整理する。
| 3本柱 | 代表サービス | 得意 Workload | 本番必須設定 |
|---|---|---|---|
| Compute | Lambda | イベント駆動・短時間処理・API バックエンド | Provisioned Concurrency + Multi-AZ Subnet |
| API | API Gateway | HTTP/WebSocket API 公開・認証・Throttle | Usage Plan + Stage Throttle + Custom Domain |
| Workflow | Step Functions | 長時間処理・承認フロー・バッチ並列 | Distributed Map + Callback Pattern + Express選定 |
全11軸との統合視点:
– IAM × Serverless: Lambda 最小特権 / Step Functions Role 責務分離 / API Gateway Logging Role
– EKS × Serverless: EKS ワークロードから SQS 経由で Lambda を非同期トリガー
– 復旧 × Serverless: Dead Letter Queue + Step Functions 再実行 + Lambda 関数バージョン管理
– コスト × Serverless: Provisioned Concurrency Schedule / Express vs Standard 選定 / Memory 最適化
– マルチアカウント × Serverless: Cross-Account Lambda Invoke / Step Functions cross-account
– Observability × Serverless: Lambda Insights + X-Ray / Step Functions Execution 可視化
– Network × Serverless: Lambda VPC Endpoint / API Gateway Private API / PrivateLink
– DevOps × Serverless: SAM Pipeline / CDK Deploy / Lambda Layer バージョン管理
– Database × Serverless: RDS Proxy 経由で Lambda から RDS 接続 / DynamoDB Streams → Lambda
落とし穴10選
- Lambda Cold Start で VPC ENI 8秒遅延 — VPC + Container Image + Java の三重苦。Provisioned Concurrency で排除する
- Lambda メモリ 128MB で CPU bottleneck — Lambda のCPU はメモリに比例。低メモリでは計算処理が遅く逆にコスト高になることも
- Lambda Container Image が 10 GB 上限に触れる — デプロイパッケージ制限。multi-stage build で不要な依存を削除する
- API Gateway Throttle 設定漏れ — Usage Plan なしで Account-level 10,000 rps を全テナントで共有
- API Gateway CORS Preflight OPTIONS 未定義 — ブラウザからの Cross-Origin リクエストが OPTIONS で失敗する
- Step Functions Express 5分上限超過 — Express は最長 5 分。長時間処理は Standard に切替が必要
- Distributed Map 未使用で 25K 状態制限に抵触 — 大量 Iteration は Standard Map state では履歴超過する
- Step Functions Callback Token 未送信 —
lambda:invokeのまま実装すると Token を渡せず外部承認が永久待ちになる - Lambda Function Role に AdministratorAccess 付与 — 最小特権に絞らないとコード脆弱性がアカウント全体の侵害につながる
- Provisioned Concurrency 過剰確保で Cost runaway — 業務時間外スケールダウンと Auto Scaling Schedule を忘れずに設定する
本番 Go-Live チェックリスト
- [ ] Lambda は 3 AZ の Subnet を指定し、Provisioned Concurrency を設定している
- [ ] Lambda Function Role は最小特権 (対象リソースへの特定 Action のみ) になっている
- [ ] API Gateway Stage に Throttle (Rate/Burst) が設定されている
- [ ] 複数テナントを扱う場合は Usage Plan + API Key でテナント分離している
- [ ] 10 万件超のバッチ処理は Distributed Map を使用している
- [ ] Callback Pattern では
waitForTaskTokenリソースを指定し Token を外部に送付している - [ ] 高頻度 Workflow (5 分以内) は Express Workflow を選択している
- [ ] Provisioned Concurrency の業務時間外スケールダウンスケジュールが設定されている
- [ ] Lambda から RDS に接続する場合は RDS Proxy を経由している
- [ ] Step Functions の実行ログが CloudWatch Logs に出力されている (Level: ERROR 以上)
- [ ] API Gateway のアクセスログが有効化されており、Custom Log Format で必要なフィールドを記録している
Vol2 公開中 — EventBridge × SQS × SNS × Kinesis 本番運用
Vol2 では Event-Driven Architecture の4本柱 (EventBridge × SQS × SNS × Kinesis) を本番運用視点で解説する。非同期処理・イベントルーティング・メッセージキュー・ストリーム処理の本番品質パターンを確立する。
| Vol2 で扱う技術 | 主なユースケース |
|---|---|
| EventBridge | イベントルーティング / スケジュール / クロスアカウント連携 |
| SQS | 非同期キュー / DLQ / FIFO / Lambda トリガー |
| SNS | Fan-out / モバイルプッシュ / Lambda 連携 |
| Kinesis Data Streams | リアルタイムストリーム処理 / シャード設計 |
全11軸 (23記事) + Serverless Vol1 — 全24記事クロスリンク
IAM入門4巻: Vol1: IAMポリシー設計の基礎 / Vol2: マルチアカウントIAM設計 / Vol3: IAM権限棚卸し自動化 / Vol4: STS × Cross-Account ロール設計
EKS本番運用3巻: Vol1: クラスター設計 × IRSA × ALB / Vol2: Observability × FluentBit / Vol3: GitOps × ArgoCD
復旧・運用編4巻: Vol1: クロスリージョンDR / Vol2: カオスエンジニアリング / Vol3: 障害対応自動化 / Vol4: Multi-Region設計
AIシリーズ2巻: Vol1: Bedrock Agents 本番運用 / Vol2: Knowledge Bases × RAG
セキュリティ本格運用2巻: Vol1: セキュリティ運用入門 / Vol2: SOC実践統合運用
コスト最適化 Vol1: Cost Explorer × Budgets × Compute Optimizer
マルチアカウント運用 Vol1: Organizations × Control Tower × Landing Zone
Observability Vol1: Application Signals × SLO × X-Ray × ADOT
Network/VPC設計2巻: Vol1: Transit Gateway × VPC Lattice × PrivateLink / Vol2: Hybrid Connectivity
DevOps/CI/CD実践2巻: Vol1: CodePipeline × CodeBuild × CodeDeploy × GitHub Actions / Vol2: Container CD × CodeArtifact × SAM Pipeline × Amplify Hosting
Database本番運用 Vol1: RDS × Aurora × DynamoDB 本番運用入門
Database本番運用 Vol2: DMS × Aurora Global Database × DynamoDB Streams × Backup戦略
Serverless本番運用 2巻: Vol1 (本記事): Lambda × API Gateway × Step Functions / Vol2: EventBridge × SQS × SNS × Kinesis
第12軸 Serverless本番運用 シリーズ起点 完結宣言
本記事により、AWS本番運用 第12軸 = Serverless本番運用 シリーズが起点 Vol1 から始動しました。
全11軸 (IAM/EKS/復旧/AI/セキュリティ/コスト/マルチアカウント/Observability/Network/DevOps/Database) の 23 記事で構築した本番運用基盤の上に、Lambda × API Gateway × Step Functions の Serverless 実行層 を加えることで、AWS 本番システムのサーバーレスワークロードが完全統合されます。
Vol2 では Event-Driven Architecture (EventBridge × SQS × SNS × Kinesis) の4本柱を本番運用視点で解説します。