Claude Code × AWS Lambda 完全ガイド|関数生成からデプロイ自動化まで
Claude CodeでAWS Lambda関数を爆速開発。ハンドラー生成・IAMポリシー設計・SAMデプロイ自動化まで、API Gateway/S3/DynamoDB連携の実例コードを完全解説。
AWS Lambda 開発でこんな経験はありませんか? ハンドラーの型定義が面倒、IAMポリシーを毎回調べながら書いている、SAM テンプレートの書き方を忘れた……。Claude Code はこれら全てを一度に解決します。
Lambda 関数の実装からIAMポリシー生成、ローカルテスト、本番デプロイまで、Claude Code を使った爆速 AWS Lambda 開発の全工程を実例コードで解説します。
なぜ Claude Code × AWS Lambda なのか
Lambda 開発の「面倒な部分」は実はほとんどがボイラープレートです。
- ハンドラー関数の型定義 (APIGatewayProxyHandler, S3Handler …)
- エラーハンドリングとレスポンス形式
- IAM ポリシーの最小権限設計
- SAM / CloudFormation テンプレートの記述
- ローカルテスト環境の設定
Claude Code はこれらを 「こういう Lambda が欲しい」の一言で生成してくれます。さらに AWS CLI や SAM CLI と組み合わせれば、コード生成からデプロイまでを一気に走らせることができます。
環境セットアップ
# 必要なツールの確認
aws --version # AWS CLI v2
sam --version # SAM CLI 1.100+
node --version # Node.js 20+
# AWS 認証情報の設定 (未設定の場合)
aws configure
# → Access Key ID, Secret Access Key, Region (ap-northeast-1), Output (json)
<!-- CLAUDE.md に追記 -->
## AWS 設定
- デフォルトリージョン: ap-northeast-1 (東京)
- Lambda ランタイム: nodejs20.x
- デプロイツール: AWS SAM
- ソースディレクトリ: src/functions/
- SAM テンプレート: template.yaml
- スタック名: my-app-{dev|staging|prod}
## IAM ポリシー方針
- 最小権限の原則を厳守
- ワイルドカード (*) は使わない
- リソース ARN は具体的に指定する
実装例1: API Gateway + Lambda (REST API)
最も基本的なパターン。HTTP リクエストを受けて処理する Lambda です。
Claude Code への指示
claude -p "
/users/{userId} に GET リクエストが来たら
DynamoDB の Users テーブルからユーザー情報を取得して返す
Lambda 関数を TypeScript で実装して。
- ランタイム: Node.js 20
- テーブル名: UsersTable (環境変数で受け取る)
- エラーハンドリング: 404/500 を適切に返す
- 型定義: @types/aws-lambda を使う
- src/functions/getUser/index.ts に出力
"
生成される実装例
// src/functions/getUser/index.ts
import {
APIGatewayProxyHandler,
APIGatewayProxyResult,
} from "aws-lambda";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient({ region: process.env.AWS_REGION });
const ddb = DynamoDBDocumentClient.from(client);
const response = (statusCode: number, body: unknown): APIGatewayProxyResult => ({
statusCode,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: JSON.stringify(body),
});
export const handler: APIGatewayProxyHandler = async (event) => {
const userId = event.pathParameters?.userId;
if (!userId) {
return response(400, { error: "userId is required" });
}
try {
const result = await ddb.send(
new GetCommand({
TableName: process.env.USERS_TABLE!,
Key: { userId },
})
);
if (!result.Item) {
return response(404, { error: `User '${userId}' not found` });
}
return response(200, result.Item);
} catch (err) {
console.error("DynamoDB error:", err);
return response(500, { error: "Internal server error" });
}
};
SAM テンプレートも自動生成
# template.yaml (抜粋)
GetUserFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/functions/getUser/index.handler
Runtime: nodejs20.x
Timeout: 10
Environment:
Variables:
USERS_TABLE: !Ref UsersTable
Policies:
- DynamoDBReadPolicy:
TableName: !Ref UsersTable
Events:
GetUserApi:
Type: Api
Properties:
Path: /users/{userId}
Method: GET
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub "${AWS::StackName}-users"
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
実装例2: S3 イベントトリガー Lambda
ファイルアップロードをトリガーに処理を走らせる Lambda。
// src/functions/generateThumbnail/index.ts
import { S3Handler } from "aws-lambda";
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import sharp from "sharp";
const s3 = new S3Client({ region: process.env.AWS_REGION });
export const handler: S3Handler = async (event) => {
const record = event.Records[0];
const bucket = record.s3.bucket.name;
const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));
// thumbnails/ プレフィックスは無視 (無限ループ防止)
if (key.startsWith("thumbnails/")) return;
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
const buffer = Buffer.from(await Body!.transformToByteArray());
const thumbnail = await sharp(buffer)
.resize(200, 200, { fit: "cover" })
.webp({ quality: 85 })
.toBuffer();
const thumbnailKey = `thumbnails/${key.replace(/\.[^.]+$/, ".webp")}`;
await s3.send(
new PutObjectCommand({
Bucket: bucket,
Key: thumbnailKey,
Body: thumbnail,
ContentType: "image/webp",
})
);
console.log(`Thumbnail created: s3://${bucket}/${thumbnailKey}`);
};
実装例3: スケジュール実行 Lambda (EventBridge)
# template.yaml の EventBridge 設定
SendReminderFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/functions/sendReminder/index.handler
Runtime: nodejs20.x
Timeout: 300
Environment:
Variables:
DATABASE_URL: !Sub "{{resolve:secretsmanager:${AWS::StackName}/database-url}}"
RESEND_API_KEY: !Sub "{{resolve:secretsmanager:${AWS::StackName}/resend-api-key}}"
Events:
DailyReminder:
Type: Schedule
Properties:
Schedule: cron(0 0 * * ? *) # UTC 0:00 = JST 9:00
IAM ポリシーを Claude Code に設計させる
claude -p "
以下の Lambda が必要な最小権限 IAM ポリシーを JSON で生成:
- S3 my-uploads から GetObject
- DynamoDB ProcessingJobs に PutItem/UpdateItem
- SQS ProcessingQueue に SendMessage
- CloudWatch Logs に書き込み
ARN はリソース名から推測して具体的に記述すること。
"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::my-uploads/*"
},
{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:UpdateItem"],
"Resource": "arn:aws:dynamodb:ap-northeast-1:*:table/ProcessingJobs"
},
{
"Effect": "Allow",
"Action": ["sqs:SendMessage"],
"Resource": "arn:aws:sqs:ap-northeast-1:*:ProcessingQueue"
},
{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
}
]
}
ローカルテストと本番デプロイ
# ビルド
sam build
# ローカルで API 起動
sam local start-api --port 3001
# 単発テスト
sam local invoke GetUserFunction --event events/get-user.json
# Claude Code で一括実行
claude -p "
sam build を実行し、
sam local invoke GetUserFunction --event events/test-get-user.json で結果確認。
問題なければ sam deploy --config-env dev を実行。
"
落とし穴5選
1. コールドスタートを考慮しない初期化
// ❌ ハンドラー内で毎回クライアントを生成
export const handler = async () => {
const ddb = new DynamoDBClient({}); // ← 毎回インスタンス化
};
// ✅ モジュールスコープで1度だけ初期化
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler = async () => { /* ddb を再利用 */ };
2. タイムアウトをデフォルト(3秒)のまま DynamoDB + 外部API なら最低10-30秒。処理内容に合わせて設定必須。
3. Secrets を環境変数直書き
# ❌ テンプレートに直書き
Environment:
Variables:
DB_PASSWORD: "my-secret"
# ✅ Secrets Manager 経由
Environment:
Variables:
DB_PASSWORD: !Sub "{{resolve:secretsmanager:myapp/db-password}}"
4. VPC Lambda のコールドスタート RDS 接続目的で VPC に入れると コールドスタートが数秒延びます。Provisioned Concurrency または RDS Proxy で対処。
5. 巨大なデプロイパッケージ
node_modules ごとパッケージすると250MBの上限に当たります。共通ライブラリは Lambda Layer に分離しましょう。
まとめ
| タスク | Claude Code の貢献 |
|---|---|
| ハンドラー実装 | 型定義・エラー処理・ロジックを一発生成 |
| SAM テンプレート | イベント・IAM・環境変数を自動出力 |
| IAM ポリシー | 最小権限設計を正確に生成 |
| ローカルテスト | sam invoke 実行と結果判断を自動化 |
| デプロイ | build + deploy を一連で実行 |
Lambda 開発で最も時間を食う「型定義とテンプレート記述」を Claude Code が丸ごと引き受けます。ビジネスロジックに集中できる環境が実装速度を3-5倍に押し上げます。
関連記事
参考資料
無料PDF: Claude Code 5分でわかるチートシート
メールアドレスを登録するだけで、A4 1枚のチートシートPDFを今すぐお送りします。
個人情報は厳重に管理し、スパムは送りません。
この記事を書いた人
Masa
現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeで新人エンジニアのオンボーディングを劇的に短縮する実践ガイド
3ヶ月かかる立ち上がり期間が2週間に。Claude Codeを新人の相棒にして、コードベース理解・環境構築・初PRまでを最速化する方法。
Claude Codeで技術的負債を可視化して計画的に削減する方法
放置された技術的負債は事業スピードを奪います。Claude Codeで負債を洗い出し、優先順位付けし、段階的に返済していく実践手順を解説。
Claude Codeで開発環境を一瞬でセットアップする方法
新しいPCでも、新しいプロジェクトでも、Claude Codeに任せれば開発環境のセットアップが数分で完了。Node.js、Docker、lint設定まで自動化する実践手法。