Use Cases (Atualizado: 02/06/2026)

Claude Code × AWS Lambda Guia Completo | Da Geração de Funções à Automação do Deploy

Crie AWS Lambda com Claude Code: Node.js 24, SAM, IAM, API Gateway, S3, logs e falhas comuns.

Claude Code × AWS Lambda Guia Completo | Da Geração de Funções à Automação do Deploy

Você já passou por isso no desenvolvimento com AWS Lambda? As definições de tipo para handlers são tediosas, você precisa pesquisar políticas IAM toda vez, esqueceu como escrever templates SAM… Claude Code resolve tudo isso de uma vez.

Da implementação de funções Lambda à geração de políticas IAM, testes locais e deploy em produção — percorremos cada etapa do desenvolvimento ultrarrápido de AWS Lambda com Claude Code usando exemplos de código reais.

Por Que Claude Code × AWS Lambda?

As “partes tediosas” do desenvolvimento Lambda são quase inteiramente código repetitivo (boilerplate).

  • Definições de tipo para funções handler (APIGatewayProxyHandler, S3Handler …)
  • Tratamento de erros e formatos de resposta
  • Design de políticas IAM com menor privilégio
  • Escrita de templates SAM / CloudFormation
  • Configuração do ambiente de testes local

Claude Code gera tudo isso com uma única frase como “Quero uma Lambda que faça X”. Combinado com AWS CLI e SAM CLI, você pode executar tudo, da geração de código ao deploy, de uma vez só.

Configuração do Ambiente

# Verificar ferramentas necessárias
aws --version        # AWS CLI v2
sam --version        # SAM CLI 1.100+
node --version       # Node.js 24+

# Configurar credenciais AWS (se ainda não configuradas)
aws configure
# → Access Key ID, Secret Access Key, Region (sa-east-1), Output (json)
<!-- Adicionar ao CLAUDE.md -->
## Configuração AWS
- Região padrão: sa-east-1 (São Paulo)
- Runtime Lambda: nodejs24.x
- Ferramenta de deploy: AWS SAM
- Diretório de código-fonte: src/functions/
- Template SAM: template.yaml
- Nome do stack: my-app-{dev|staging|prod}

## Diretrizes de Política IAM
- Seguir rigorosamente o princípio do menor privilégio
- Não usar wildcards (*)
- Especificar ARNs de recursos de forma concreta

Exemplo 1: API Gateway + Lambda (REST API)

O padrão mais fundamental — uma Lambda que recebe requisições HTTP e as processa.

Instruções para o Claude Code

claude -p "
Quando uma requisição GET chegar em /users/{userId},
recuperar as informações do usuário da tabela Users no DynamoDB e retorná-las.
Implementar a função Lambda em TypeScript.

- Runtime: Node.js 24
- Nome da tabela: UsersTable (recebido via variável de ambiente)
- Tratamento de erros: retornar respostas 404/500 apropriadas
- Definições de tipo: usar @types/aws-lambda
- Saída para: src/functions/getUser/index.ts
"

Implementação Gerada

// 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" });
  }
};

Template SAM Também É Gerado Automaticamente

# template.yaml (trecho)
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

Exemplo 2: Lambda com Gatilho de Evento S3

Uma Lambda acionada por uploads de arquivos para executar processamentos.

// 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, " "));

  // Ignorar prefixo thumbnails/ (evitar loop infinito)
  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(`Miniatura criada: s3://${bucket}/${thumbnailKey}`);
};

Exemplo 3: Lambda Agendada (EventBridge)

# Configuração do EventBridge no template.yaml
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 = BRT 21:00 (horário de Brasília)

Deixar o Claude Code Projetar as Políticas IAM

claude -p "
Gerar uma política IAM de menor privilégio em JSON para uma Lambda que precisa:
- GetObject do bucket S3 my-uploads
- PutItem/UpdateItem na tabela DynamoDB ProcessingJobs
- SendMessage para a fila SQS ProcessingQueue
- Escrever no CloudWatch Logs

Inferir ARNs específicos a partir dos nomes de recursos fornecidos.
"
{
  "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:sa-east-1:*:table/ProcessingJobs"
    },
    {
      "Effect": "Allow",
      "Action": ["sqs:SendMessage"],
      "Resource": "arn:aws:sqs:sa-east-1:*:ProcessingQueue"
    },
    {
      "Effect": "Allow",
      "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
    }
  ]
}

Testes Locais e Deploy em Produção

# Build
sam build

# Iniciar API localmente
sam local start-api --port 3001

# Invocação de teste única
sam local invoke GetUserFunction --event events/get-user.json

# Executar tudo com Claude Code
claude -p "
Executar sam build,
verificar resultados com sam local invoke GetUserFunction --event events/test-get-user.json.
Se tudo estiver bem, executar sam deploy --config-env dev.
"

As 5 Armadilhas Mais Comuns

1. Inicialização que ignora cold starts

// ❌ Criar o cliente dentro do handler a cada invocação
export const handler = async () => {
  const ddb = new DynamoDBClient({});  // ← instanciado a cada invocação
};

// ✅ Inicializar uma vez no escopo do módulo
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler = async () => { /* reutilizar ddb */ };

2. Deixar o timeout no valor padrão (3 segundos) Para DynamoDB + APIs externas, defina pelo menos 10-30 segundos. Sempre configure de acordo com os requisitos reais de processamento.

3. Escrever segredos diretamente em variáveis de ambiente

# ❌ Hard-coded no template
Environment:
  Variables:
    DB_PASSWORD: "my-secret"

# ✅ Via Secrets Manager
Environment:
  Variables:
    DB_PASSWORD: !Sub "{{resolve:secretsmanager:myapp/db-password}}"

4. Atrasos de cold start com Lambda em VPC Colocar uma Lambda dentro de uma VPC para conectividade com RDS adiciona vários segundos ao cold start. Resolva com Provisioned Concurrency ou RDS Proxy.

5. Pacotes de deploy grandes demais Empacotar node_modules junto pode atingir o limite de 250 MB. Mova as bibliotecas compartilhadas para um Lambda Layer.

Resumo

TarefaContribuição do Claude Code
Implementação do handlerGerar definições de tipo, tratamento de erros e lógica de uma só vez
Template SAMSaída automática de eventos, IAM e variáveis de ambiente
Política IAMGerar com precisão designs de menor privilégio
Testes locaisAutomatizar a execução do sam invoke e avaliação de resultados
DeployExecutar build + deploy como um fluxo de trabalho unificado

Claude Code assume as partes mais demoradas do desenvolvimento Lambda — definições de tipo e escrita de templates. Focar na lógica de negócio pode multiplicar a velocidade de implementação em 3-5 vezes.

Artigos Relacionados

Quando Lambda faz sentido e quando não

Lambda combina com trabalho curto, orientado a evento e seguro de repetir: API de pedido, imagem após upload S3, relatório diário EventBridge e webhooks Stripe/GitHub. Não combina com workers longos, conexões persistentes, modelos grandes aquecidos ou WebSocket stateful complexo. Peça ao Claude Code motivos a favor e contra antes do código.

Termos em linguagem simples

TermPlain meaning
handlerThe function Lambda calls. API Gateway passes an HTTP event; S3 passes an object event.
eventThe JSON payload given to Lambda. API Gateway, S3, and EventBridge shapes are different.
least privilegeGrant only the exact actions and resources the function needs.
cold startThe slower first run when Lambda creates a new execution environment.
idempotencyThe same event can run twice without duplicate payment, email, or database writes.

Teste unitário copiável para 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);
  });
});

Separe eventos de API Gateway, S3 e EventBridge

API Gateway precisa destatusCode ebody. S3 lê bucket/key emRecords. EventBridge geralmente usasource, detail-type e detail. Nomeie o trigger: HTTP API v2, S3 ObjectCreated ou EventBridge schedule.

Variáveis, Secrets Manager e IAM de menor privilégio

Variáveis são para configuração comoUSERS_TABLE eAPP_STAGE. API keys, senhas e secrets de webhook ficam no Secrets Manager; Lambda recebe só o ARN. IAM deve usar actions e ARNs específicos.

CloudWatch Logs, retries e idempotência

CloudWatch Logs é o primeiro diagnóstico. Sem logs, confira região, função, permissões do role e stack. S3, EventBridge e chamadas async podem retry; use IDs como chaves de idempotência.

Prompt de revisão segura para 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 de monetização, treinamento e consultoria

ClaudeCodeLab oferece treinamento e consultoria para Lambda, IAM, SAM, auditoria de logs e gates de revisão. Individuais começam com PDF grátis e Gumroad; equipes usam treinamento e consultoria para permissões, approvals e receita.

Resultado prático

Separei exemplos em handler e tests verificáveis comnpm test. Não rodeisam deploy real porque conta, região, ARN e tabela variam. Produção deve registrarsam validate --lint, sam build, sam local invoke, logs e IAM diff.

Referências

#claude-code #aws #lambda #serverless #api-gateway #typescript
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.