Use Cases (更新: 2026/6/1)

Claude Code AWS Lambda 实战指南:Node.js、IAM 与 API Gateway

用Claude Code构建Node.js Lambda,完成本地测试、最小权限IAM、环境变量、API Gateway和日志检查。

Claude Code AWS Lambda 实战指南:Node.js、IAM 与 API Gateway

用 Claude Code 写 AWS Lambda 很快:一次描述需求,它就能生成 handler、测试事件、IAM policy 草稿、部署命令和 review checklist。问题是,AWS 权限和费用不是草稿。Claude Code 可以帮助准备材料,但是否授予权限、是否公开 API、是否创建会计费的资源,必须由人来确认。

本文用一个团队能复用的最小流程说明:创建 Node.js Lambda、本地测试、把 IAM 收窄到接近最小权限、设置环境变量、连接 API Gateway、查看 CloudWatch Logs、用 zip package 更新代码,并把 Claude Code 放进安全 review loop。Lambda 可以理解为“事件来了才启动的小运行环境”,IAM 是“决定函数可以做什么的权限表”,API Gateway 是“把 HTTP 请求转给 Lambda 的入口”。

开始前建议打开官方文档:AWS Lambda 入门Node.js Lambda 指南Lambda 环境变量CloudWatch Logs 监控Claude Code common workflows。本文示例按 2026 年 6 月 1 日的 Node.js 24 Lambda runtime 编写。

适合哪些场景

Lambda 适合不想长期运行服务器、但又需要可靠处理的短任务。Claude Code 最适合生成结构化草稿,再由 reviewer 做最终判断。

使用场景为什么适合 LambdaClaude Code 可以起草人必须检查
Webhook 接收支付、表单、SaaS 通知通常很短签名校验、事件 fixture、失败响应secret、重试、重复事件
内部 JSON API小 API 不需要常驻服务器handler、API Gateway 命令、日志格式认证、CORS、公开范围、费用
批处理入口CSV 导入、图片处理、通知任务可以小步开始输入校验、结构化日志、错误分类timeout、重试策略、安全删除

刚验证时,AWS CLI 加 zip package 很快;团队长期运行时,建议迁移到 SAM、CDK 或其他 IaC review 流程。

方法适合注意点
AWS Console只看一次行为手工步骤很难进入 review 历史
AWS CLI + zip小型可复现验证IAM 和环境变量必须仔细检查
SAM / CDK团队持续运维IaC review 和部署批准变成必需
flowchart LR
  A[Claude Code 起草] --> B[本地 Node.js 测试]
  B --> C[人检查 IAM 和环境变量]
  C --> D[zip package 部署到 dev]
  D --> E[通过 API Gateway 测试]
  E --> F[阅读 CloudWatch Logs]
  F --> A

1. 创建 Node.js Lambda handler

先写一个没有外部依赖的 index.mjs。它同时兼容 HTTP API v2 事件和较旧的 REST API 事件,并返回 API Gateway 期望的结构。

// index.mjs
import crypto from "node:crypto";

const allowedStages = new Set(["dev", "staging", "prod"]);

function readConfig() {
  const stage = process.env.APP_STAGE ?? "dev";
  if (!allowedStages.has(stage)) {
    throw new Error(`Invalid APP_STAGE: ${stage}`);
  }

  return {
    stage,
    tableName: process.env.TABLE_NAME ?? "local-orders",
    logLevel: process.env.LOG_LEVEL ?? "info",
  };
}

function log(level, message, details = {}) {
  console.log(
    JSON.stringify({
      level,
      message,
      service: "orders-api",
      ...details,
    })
  );
}

function json(statusCode, body) {
  return {
    statusCode,
    headers: {
      "content-type": "application/json",
    },
    body: JSON.stringify(body),
  };
}

function parseBody(event) {
  if (!event.body) return {};
  const raw = event.isBase64Encoded
    ? Buffer.from(event.body, "base64").toString("utf8")
    : event.body;
  return JSON.parse(raw);
}

export async function handler(event = {}, context = {}) {
  const config = readConfig();
  const method = event.requestContext?.http?.method ?? event.httpMethod ?? "GET";
  const path = event.rawPath ?? event.path ?? "/";
  const requestId = context.awsRequestId ?? "local";

  log("info", "request.start", {
    requestId,
    method,
    path,
    stage: config.stage,
  });

  try {
    if (method === "GET" && path === "/health") {
      return json(200, { ok: true, stage: config.stage });
    }

    if (method === "POST" && path === "/orders") {
      const payload = parseBody(event);
      const orderId = payload.orderId ?? crypto.randomUUID();

      log("info", "order.accepted", {
        requestId,
        orderId,
        tableName: config.tableName,
      });

      return json(202, {
        orderId,
        status: "accepted",
        storedIn: config.tableName,
      });
    }

    return json(404, { error: "not_found", method, path });
  } catch (error) {
    log("error", "request.failed", {
      requestId,
      errorName: error.name,
      errorMessage: error.message,
    });

    return json(500, { error: "internal_error", requestId });
  }
}

这里还没有写入 DynamoDB,这是有意的。初学者第一步应该先确认事件接收、JSON 解析、响应格式和日志都正常,再增加数据库和更多 IAM 权限。

2. 用事件 fixture 本地测试

fixture 是保存下来的固定测试输入。让 Claude Code 生成之后,把它提交到仓库,reviewer 就能复现问题。

{
  "version": "2.0",
  "routeKey": "POST /orders",
  "rawPath": "/orders",
  "requestContext": {
    "http": {
      "method": "POST",
      "path": "/orders"
    }
  },
  "headers": {
    "content-type": "application/json"
  },
  "body": "{\"orderId\":\"demo-1001\",\"amount\":3200,\"currency\":\"JPY\"}",
  "isBase64Encoded": false
}

保存为 events/create-order.json,再加入本地 runner。

// local-test.mjs
import { readFile } from "node:fs/promises";
import { handler } from "./index.mjs";

process.env.APP_STAGE = "dev";
process.env.TABLE_NAME = "orders-dev";
process.env.LOG_LEVEL = "debug";

const eventPath = process.argv[2] ?? "events/create-order.json";
const event = JSON.parse(await readFile(eventPath, "utf8"));

const result = await handler(event, { awsRequestId: "local-001" });
console.log(JSON.stringify(result, null, 2));

先在本地执行:

node local-test.mjs events/create-order.json

如果本地没有返回 statusCode: 202,部署到 AWS 只会让调试更慢。fixture 也能让 Claude Code 基于真实失败输入分析,而不是凭空猜测。

3. IAM 从最小权限开始

不要给 Lambda execution role 直接附加 AdministratorAccess。先只给日志权限,真正使用数据服务时再添加对应资源。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CreateOwnLogGroupIfMissing",
      "Effect": "Allow",
      "Action": "logs:CreateLogGroup",
      "Resource": "arn:aws:logs:ap-northeast-1:123456789012:*"
    },
    {
      "Sid": "WriteOwnLambdaLogs",
      "Effect": "Allow",
      "Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/claude-orders-dev:*"
    },
    {
      "Sid": "ReadWriteOnlyOrdersTable",
      "Effect": "Allow",
      "Action": ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:Query"],
      "Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/orders-dev"
    }
  ]
}

这只是草稿。替换 account、region、function name 和 table name;在真的调用 DynamoDB 前,删除 DynamoDB 区块。权限审查可以继续参考站内的 AWS IAM 指南

4. 用 AWS CLI 部署 zip package

下面的命令会创建真实 AWS 资源,可能产生费用。请在 dev account 中执行,并先确认 region 和删除步骤。

export AWS_REGION=ap-northeast-1
export FUNCTION_NAME=claude-orders-dev
export ROLE_NAME=claude-orders-dev-lambda-role
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

zip function.zip index.mjs

创建 trust-policy.json,允许 Lambda 服务使用这个 role。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

把上面的 IAM 草稿保存为 lambda-policy.json,然后创建 role 和函数。

aws iam create-role \
  --role-name "$ROLE_NAME" \
  --assume-role-policy-document file://trust-policy.json

aws iam put-role-policy \
  --role-name "$ROLE_NAME" \
  --policy-name claude-orders-dev-inline \
  --policy-document file://lambda-policy.json

ROLE_ARN=$(aws iam get-role \
  --role-name "$ROLE_NAME" \
  --query "Role.Arn" \
  --output text)

aws lambda create-function \
  --function-name "$FUNCTION_NAME" \
  --runtime nodejs24.x \
  --handler index.handler \
  --zip-file fileb://function.zip \
  --role "$ROLE_ARN" \
  --architectures arm64 \
  --timeout 10 \
  --memory-size 128 \
  --environment "Variables={APP_STAGE=dev,TABLE_NAME=orders-dev,LOG_LEVEL=info}" \
  --region "$AWS_REGION"

只更新代码时,不需要重建函数。

zip function.zip index.mjs

aws lambda update-function-code \
  --function-name "$FUNCTION_NAME" \
  --zip-file fileb://function.zip \
  --region "$AWS_REGION"

更新环境变量时要特别小心。update-function-configuration 指定 Variables 时,会整体替换变量表。先读取现有配置,再修改。密码、API key 等 secret 不要直接放进环境变量,优先考虑 Secrets Manager 或 Parameter Store。

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --environment "Variables={APP_STAGE=dev,TABLE_NAME=orders-dev,LOG_LEVEL=debug}" \
  --region "$AWS_REGION"

5. 用 API Gateway 和 CloudWatch Logs 验证

先直接 invoke Lambda。

aws lambda invoke \
  --function-name "$FUNCTION_NAME" \
  --payload fileb://events/create-order.json \
  --region "$AWS_REGION" \
  response.json

cat response.json

然后创建 HTTP API。它会暴露 public endpoint,所以执行前要确认认证、CORS、rate limit 和删除计划。

API_ID=$(aws apigatewayv2 create-api \
  --name claude-orders-dev-api \
  --protocol-type HTTP \
  --target "arn:aws:lambda:${AWS_REGION}:${ACCOUNT_ID}:function:${FUNCTION_NAME}" \
  --query "ApiId" \
  --output text)

aws lambda add-permission \
  --function-name "$FUNCTION_NAME" \
  --statement-id AllowHttpApiInvoke \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-arn "arn:aws:execute-api:${AWS_REGION}:${ACCOUNT_ID}:${API_ID}/*/*" \
  --region "$AWS_REGION"

API_ENDPOINT=$(aws apigatewayv2 get-api \
  --api-id "$API_ID" \
  --query "ApiEndpoint" \
  --output text)

curl -s "$API_ENDPOINT/health"
curl -s -X POST "$API_ENDPOINT/orders" \
  -H "content-type: application/json" \
  -d '{"amount":3200,"currency":"JPY"}'

测试后马上看日志。

aws logs tail "/aws/lambda/${FUNCTION_NAME}" \
  --follow \
  --region "$AWS_REGION"

如果没有日志,检查 region、function name、logs:CreateLogStreamlogs:PutLogEvents。如果 API Gateway 返回 500,检查 Lambda response 是否包含 statusCodeheadersbody。更完整的监控和 API 设计可以继续看 AWS CloudWatch 指南AWS API Gateway 指南

用于 Lambda review 的 Claude prompt

不要让 Claude Code 直接部署。先让它解释风险。

You are reviewing a Node.js AWS Lambda change for a team repository.

Scope:
- Files: index.mjs, events/*.json, IAM policy JSON, deployment commands in docs
- Runtime: nodejs24.x
- Entry point: index.handler

Review for:
1. API Gateway event compatibility and response shape
2. Input validation and JSON parsing failures
3. Environment variables that overwrite existing values
4. IAM actions that are wider than needed
5. CloudWatch logs that expose secrets or personal data
6. AWS resources that can create unexpected cost
7. Local test commands that a reviewer can copy and run

Return:
- blocking issues
- non-blocking improvements
- exact commands to verify locally
- questions a human must answer before deploying

安全顺序是:先探索,再计划,再编辑,本地测试,只部署到 dev,查看日志,最后由人批准 IAM 和费用相关修改。要把这个 proof of concept 迁移到 CI/CD 和 IaC,可以继续看 AWS deployment guide

常见陷阱

第一个陷阱是没有本地复现就部署。事件结构错了,用 fixture 比在 CloudWatch 里找更快。

第二个陷阱是把 secret 直接放进环境变量。环境变量适合配置,但 secret 需要访问控制、轮换和审计。

第三个陷阱是 IAM 太宽。dynamodb:*Resource: "*" 会让 demo 更容易通过,也会扩大事故范围。让 Claude Code 逐行解释每个 action 的必要性。

第四个陷阱是没有 owner 就公开 API Gateway URL。分享 URL 前先决定认证、CORS、throttling、日志和 cleanup date。

第五个陷阱是忽略费用。Lambda 看起来很小,但 API Gateway、CloudWatch Logs、DynamoDB、NAT 和外部 API 调用都会产生费用。

ClaudeCodeLab 把这类 review 方法整理成了实用的 Claude Code templates 和 training material。如果你的团队需要围绕真实仓库设计 AWS 权限、CLAUDE.md、review prompt 和部署批准规则,可以查看 Claude Code 咨询与培训页面

验证结束后,删除 proof-of-concept 资源。

aws apigatewayv2 delete-api --api-id "$API_ID" --region "$AWS_REGION"
aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$AWS_REGION"
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name claude-orders-dev-inline
aws iam delete-role --role-name "$ROLE_NAME"

实际试过本文流程后,最明显的收益是 Claude Code 能把 handler、fixture、IAM 草稿和 CLI 命令放在同一个可 review 的上下文里。真正危险的不是代码生成,而是权限和公开范围判断。可靠顺序是:先本地 fixture,再 dev 部署,再 CloudWatch evidence,最后由人审查 IAM 和费用,然后才考虑生产环境。

#Claude Code #AWS Lambda #serverless #AWS #Node.js #IAM
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。