Use Cases

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

Desenvolva funções AWS Lambda em alta velocidade com Claude Code. Tutorial completo com código real: geração de handlers, design de políticas IAM, automação SAM, integrações API Gateway/S3/DynamoDB.

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 20+

# 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: nodejs20.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 20
- 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: 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

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: 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 = 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

Referências

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

Leve seu fluxo no Claude Code a outro nível

50 modelos de prompt testados em campo, prontos para colar direto no Claude Code.

Grátis

PDF gratuito: Cheatsheet do Claude Code em 5 minutos

Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.

Cuidamos dos seus dados pessoais e nunca enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.