Claude Code × AWS Lambda 完全指南 | 从函数生成到部署自动化
用Claude Code安全构建AWS Lambda:Node.js 24、SAM、IAM、API Gateway、S3、日志与避坑。
在 AWS Lambda 开发中,你是否有过这样的经历?Handler 的类型定义繁琐,每次都要查阅 IAM 策略,忘记了 SAM 模板的写法……Claude Code 可以一次性解决所有这些问题。
从 Lambda 函数实现到 IAM 策略生成、本地测试,再到生产环境部署——我们将通过真实代码示例,完整解析使用 Claude Code 进行极速 AWS Lambda 开发的每个环节。
为什么选择 Claude Code × AWS Lambda?
Lambda 开发中”繁琐的部分”其实几乎全都是样板代码(boilerplate)。
- Handler 函数的类型定义(APIGatewayProxyHandler、S3Handler …)
- 错误处理与响应格式
- 最小权限 IAM 策略设计
- SAM / CloudFormation 模板编写
- 本地测试环境配置
Claude Code 只需一句话”我需要一个做 X 的 Lambda”,就能生成上述所有内容。再结合 AWS CLI 和 SAM CLI,从代码生成到部署,可以一气呵成。
环境搭建
# 确认所需工具
aws --version # AWS CLI v2
sam --version # SAM CLI 1.100+
node --version # Node.js 24+
# 配置 AWS 凭证(如未配置)
aws configure
# → Access Key ID, Secret Access Key, Region (ap-northeast-1), Output (json)
<!-- 添加到 CLAUDE.md -->
## AWS 配置
- 默认区域:ap-northeast-1(东京)
- Lambda 运行时:nodejs24.x
- 部署工具:AWS SAM
- 源代码目录:src/functions/
- SAM 模板:template.yaml
- Stack 名称:my-app-{dev|staging|prod}
## IAM 策略原则
- 严格遵守最小权限原则
- 不使用通配符(*)
- 具体指定资源 ARN
实现示例 1:API Gateway + Lambda(REST API)
最基础的模式——接收 HTTP 请求并进行处理的 Lambda。
向 Claude Code 下达指令
claude -p "
当 /users/{userId} 收到 GET 请求时,
从 DynamoDB 的 Users 表中获取用户信息并返回。
用 TypeScript 实现 Lambda 函数。
- 运行时:Node.js 24
- 表名: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: nodejs24.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(`缩略图已生成:s3://${bucket}/${thumbnailKey}`);
};
实现示例 3:定时执行 Lambda(EventBridge)
# template.yaml 中的 EventBridge 配置
SendReminderFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/functions/sendReminder/index.handler
Runtime: nodejs24.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 = 北京时间 8:00
让 Claude Code 设计 IAM 策略
claude -p "
为以下 Lambda 生成 JSON 格式的最小权限 IAM 策略:
- 从 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。
"
五大常见陷阱
1. 未考虑冷启动的初始化
// ❌ 每次在 Handler 内部创建客户端
export const handler = async () => {
const ddb = new DynamoDBClient({}); // ← 每次调用都会实例化
};
// ✅ 在模块作用域只初始化一次
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler = async () => { /* 复用 ddb */ };
2. 超时保持默认值(3 秒) 对于 DynamoDB + 外部 API,至少设置 10-30 秒。务必根据实际处理内容进行配置。
3. 将密钥直接写入环境变量
# ❌ 直接写入模板
Environment:
Variables:
DB_PASSWORD: "my-secret"
# ✅ 通过 Secrets Manager 获取
Environment:
Variables:
DB_PASSWORD: !Sub "{{resolve:secretsmanager:myapp/db-password}}"
4. VPC Lambda 的冷启动问题 为了连接 RDS 而将 Lambda 放入 VPC,会导致冷启动延迟数秒。使用 Provisioned Concurrency 或 RDS Proxy 来解决。
5. 部署包体积过大
将 node_modules 整体打包可能触及 250 MB 上限。将公共库分离到 Lambda Layer 中。
总结
| 任务 | Claude Code 的贡献 |
|---|---|
| Handler 实现 | 一次性生成类型定义、错误处理和业务逻辑 |
| SAM 模板 | 自动输出事件、IAM 和环境变量配置 |
| IAM 策略 | 精确生成最小权限设计 |
| 本地测试 | 自动化执行 sam invoke 并判断结果 |
| 部署 | 将 build + deploy 作为一套流程执行 |
Lambda 开发中最耗时的”类型定义与模板编写”,由 Claude Code 全权包办。专注于业务逻辑的开发环境,能让实现速度提升 3-5 倍。
Lambda适合与不适合的场景
Lambda适合短小、事件驱动、可安全重试的任务,例如订单查询API、S3上传后的图片处理、EventBridge日次报表、Stripe或GitHub Webhook。不适合长时间常驻、低延迟长连接、大模型常驻或复杂WebSocket状态。让Claude Code先写“为什么适合”和“为什么不适合”,再生成代码。
术语用简单话说明
| Term | Plain meaning |
|---|---|
| handler | The function Lambda calls. API Gateway passes an HTTP event; S3 passes an object event. |
| event | The JSON payload given to Lambda. API Gateway, S3, and EventBridge shapes are different. |
| least privilege | Grant only the exact actions and resources the function needs. |
| cold start | The slower first run when Lambda creates a new execution environment. |
| idempotency | The same event can run twice without duplicate payment, email, or database writes. |
Node.js 24可复制运行的单元测试
// test/getUser.test.ts
import { describe, expect, it, vi } from "vitest";
import type { APIGatewayProxyEvent } from "aws-lambda";
const mockSend = vi.fn();
vi.mock("@aws-sdk/lib-dynamodb", async () => {
const actual = await vi.importActual<typeof import("@aws-sdk/lib-dynamodb")>("@aws-sdk/lib-dynamodb");
return { ...actual, DynamoDBDocumentClient: { from: () => ({ send: mockSend }) } };
});
const { handler } = await import("../src/functions/getUser/index");
function event(userId?: string): APIGatewayProxyEvent {
return {
pathParameters: userId ? { userId } : null,
httpMethod: "GET",
path: userId ? "/users/" + userId : "/users",
headers: {},
multiValueHeaders: {},
queryStringParameters: null,
multiValueQueryStringParameters: null,
body: null,
isBase64Encoded: false,
requestContext: {} as APIGatewayProxyEvent["requestContext"],
resource: "/users/{userId}",
stageVariables: null,
};
}
describe("getUser Lambda", () => {
it("returns 200 when the user exists", async () => {
process.env.USERS_TABLE = "UsersTable";
mockSend.mockResolvedValueOnce({ Item: { userId: "u-1", name: "Masa" } });
const res = await handler(event("u-1"), {} as never, vi.fn());
expect(res.statusCode).toBe(200);
expect(JSON.parse(res.body).userId).toBe("u-1");
});
it("returns 400 when path parameter is missing", async () => {
const res = await handler(event(), {} as never, vi.fn());
expect(res.statusCode).toBe(400);
});
});
区分API Gateway、S3、EventBridge事件形状
API Gateway需要statusCode和body。S3从Records读取bucket/key。EventBridge通常看source、detail-type和detail。请在提示词中明确HTTP API v2、S3 ObjectCreated或EventBridge schedule。
环境变量、Secrets Manager与最小权限IAM
环境变量用于USERS_TABLE、APP_STAGE等配置。API key、数据库密码和Webhook签名密钥放在Secrets Manager,只把Secret ARN传给Lambda。IAM用具体Action和ARN,看到Resource: "*"或s3:*就重新审查。
CloudWatch Logs、重试与幂等性
CloudWatch Logs是排查Lambda的第一入口。没有日志时检查区域、函数名、执行角色日志权限和stack名。S3、EventBridge和异步调用可能重试,要用event ID或业务ID做幂等键。
让Claude Code做安全审查的提示词
Review this AWS Lambda change before production.
Check handler shape, API Gateway/S3/EventBridge event type, IAM least privilege, Secrets Manager usage, CloudWatch Logs, retries, idempotency, cold starts, timeout, memory, and cost risk.
Return blockers first, then recommended fixes, missing tests, and human approvals required before deploy.
变现、培训与咨询CTA
ClaudeCodeLab提供Lambda、IAM、SAM、日志审计和Claude Code审查流程的培训咨询。个人可先看免费PDF和Gumroad资料;团队上线生产请通过培训与咨询设计权限、部署审批和收入路径。
实际验证结果
我把示例拆成handler和test,可用npm test本地检查。真实sam deploy依赖账号、区域、Secret ARN和DynamoDB表名,所以此处不执行;生产前应记录sam validate --lint、sam build、sam local invoke、CloudWatch Logs和IAM diff。
补充官方链接
- Lambda runtimes
- Building Lambda functions with Node.js
- Working with Lambda environment variables
- Security best practices in IAM
- Sending Lambda function logs to CloudWatch Logs
- Invoking Lambda with API Gateway
- Using an S3 trigger to invoke Lambda
- Retries and failures in Lambda applications
内部链接检查清单
相关文章
参考资料
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
从Obsidian到CLAUDE.md的Claude Code流程:不再反复解释上下文
把 Obsidian 工作笔记整理成 CLAUDE.md 运行说明,让 Claude Code 每次都带着正确上下文开始。
Claude Code 收入 CTA 路由:从文章分流到 PDF、Gumroad 与咨询
用 Claude Code 按读者意图把文章流量分到免费 PDF、Gumroad 教材或咨询入口。
Claude Code 团队交接规则: 把审查证据、权限、回滚和收入路径一起交付
面向团队的 Claude Code 交接格式: 证据、权限、回滚、免费 PDF、Gumroad 与咨询路径都要可审查。