Use Cases

Claude Code × AWS Lambda 完全指南 | 从函数生成到部署自动化

使用Claude Code极速开发AWS Lambda函数。完整教程含真实代码示例:Handler生成、IAM策略设计、SAM部署自动化、API Gateway/S3/DynamoDB集成全解析。

在 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 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
- 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 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(`缩略图已生成: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 = 北京时间 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 倍。

相关文章

参考资料

#claude-code #aws #lambda #serverless #api-gateway #typescript

让你的 Claude Code 工作流更上一层楼

50 个经过实战检验的提示词模板,现在就能复制粘贴到 Claude Code 中使用。

免费

免费 PDF:5 分钟看懂 Claude Code 速查表

只需留下邮箱,我们就会立即把这份 A4 一页速查表 PDF 发送给你。

我们会严格保护你的个人信息,绝不发送垃圾邮件。

Masa

本文作者

Masa

深度使用 Claude Code 的工程师。运营 claudecode-lab.com——一个涵盖 10 种语言、超过 2,000 页内容的科技媒体。