Deploy na AWS com Claude Code: CDK, GitHub Actions, IAM, logs e rollback
Publique uma API pequena na AWS com Claude Code, CDK, OIDC, IAM mínimo, logs, rollback e controle de custos.
O jeito arriscado de usar Claude Code para deploy na AWS é pedir “crie uma arquitetura AWS” e aceitar a primeira resposta. Deploy pronto para operar não é só diagrama. Ele precisa de IaC executável, IAM com permissões limitadas, gestão de segredos, logs, rollback e limites de custo.
Neste guia vamos implementar um caminho seguro para uma aplicação web pequena ou API: API Gateway + Lambda + AWS CDK + GitHub Actions. CDK é Infrastructure as Code: recursos AWS descritos em código, em vez de cliques manuais no console. IAM é o sistema de permissões que define quem pode fazer cada ação. OIDC permite que o GitHub Actions assuma uma role da AWS com credenciais temporárias, sem guardar AWS keys permanentes.
Claude Code ajuda porque lê o repositório, edita vários arquivos, roda cdk synth e cdk diff, explica erros de deploy e transforma o processo em documentação. Para o produto, use a documentação oficial do Claude Code. Para AWS, consulte AWS CDK NodejsFunction, API Gateway Lambda proxy integration, variáveis de ambiente do Lambda, CloudWatch Logs para Lambda e boas práticas de IAM.
Escolha o alvo AWS antes de codar
Se o alvo ficar vago, Claude Code tende a montar uma solução maior do que o necessário.
| Opção | Quando usar | Vantagem | Atenção |
|---|---|---|---|
| Lambda + API Gateway | APIs pequenas, formulários, webhooks, backends leves | Pouca administração de servidor e bom começo para baixo tráfego | Não é ideal para tarefas longas, conexões persistentes ou grandes contêineres |
| ECS/Fargate + ALB | APIs Docker, serviços sempre ativos, API com workers | Mais liberdade para contêineres e migração de apps existentes | Exige VPC, ALB, task definitions, scaling e build de imagem |
| Amplify ou S3 + CloudFront | Sites estáticos, SPAs, apps focadas em frontend | Entrega rápida via CDN e operação simples | API, autenticação e jobs precisam de desenho separado |
Aqui escolhemos Lambda + API Gateway porque é um caso comum em consultoria: publicar uma API pequena de forma segura sem criar uma plataforma complexa. Para continuar, veja Claude Code AWS Lambda, Claude Code AWS IAM, Claude Code API Gateway e boas práticas de segurança com Claude Code.
flowchart LR
User[Usuário] --> Api[API Gateway]
Api --> Fn[Lambda Node.js API]
Fn --> Secret[Secrets Manager]
Fn --> Logs[CloudWatch Logs]
GitHub[GitHub Actions OIDC] --> CDK[AWS CDK deploy]
CDK --> Api
CDK --> Fn
Casos de uso práticos
O primeiro caso é formulário de contato ou captura de leads. O frontend pode continuar no site atual, e apenas o endpoint de envio fica em API Gateway + Lambda. Throttling, API key e CloudWatch Logs ajudam a investigar spam e falhas.
O segundo caso é uma API MVP para SaaS. Comece pequeno, com rotas como /v1/health, /v1/contact e /v1/webhook. Diga ao Claude Code que VPC, RDS, filas e contêineres só devem aparecer quando houver uma necessidade real.
O terceiro caso é webhook interno: alertas no Slack, callbacks de CMS, aprovações ou pequenas ações administrativas. Lambda funciona bem quando cada requisição termina rápido. Se precisar de retry, processamento longo ou fan-out, adicione SQS ou Step Functions de propósito.
O quarto caso é migrar deploy manual para CI/CD. Muitas equipes ainda deployam do notebook ou alteram recursos no console AWS. Claude Code pode levar esse fluxo para CDK e GitHub Actions, mas aprovação de produção, rollback e risco continuam sendo decisões humanas.
Defina regras para Claude Code
Crie um CLAUDE.md na raiz do repositório para evitar que uma API pequena vire uma arquitetura cara.
# AWS deployment rules
- Use AWS CDK v2 and TypeScript.
- Target region: sa-east-1 unless explicitly changed.
- Do not create VPC resources for this small API unless required.
- Prefer API Gateway + Lambda for the first release.
- Runtime secrets must come from AWS Secrets Manager, not plaintext env vars.
- Use IAM grants such as secret.grantRead(handler) instead of wildcard policies.
- Add CloudWatch log retention and reserved concurrency.
- Before deploy, run npm test, npx cdk synth, and npx cdk diff.
- Never paste AWS access keys into files or GitHub Secrets.
Depois peça uma implementação com escopo claro:
Adicione um SmallApiStack CDK v2 neste repositório.
Crie uma API REST no API Gateway e uma Lambda Node.js 20 com /v1/health e /v1/contact.
Leia a configuração de runtime do Secrets Manager: prod/claude-code-demo/api.
Mantenha a role de execução da Lambda com mínimo privilégio e adicione retenção de logs, reserved concurrency e throttling no API Gateway.
O workflow do GitHub Actions deve usar apenas OIDC. Não use AWS keys permanentes.
Depois da edição, rode npm test, npx cdk synth e npx cdk diff, e explique o resultado.
Crie o projeto CDK
Você precisa de Node.js, AWS CLI v2, AWS CDK CLI e um perfil AWS autenticado. Os comandos abaixo são Bash; no Windows, use WSL ou Git Bash.
mkdir claude-code-aws-api
cd claude-code-aws-api
npx cdk init app --language typescript
npm install @aws-sdk/client-secrets-manager
npm install --save-dev esbuild @types/aws-lambda
mkdir -p lambda
aws sts get-caller-identity
Crie a configuração de runtime uma vez. API keys reais, senhas e tokens não devem ir para Git nem para variáveis de ambiente em texto puro.
aws secretsmanager create-secret \
--name prod/claude-code-demo/api \
--secret-string '{"supportQueue":"aws-consulting"}' \
--region sa-east-1
Implemente a Lambda
Crie lambda/handler.ts. O código registra apenas metadados operacionais, sem imprimir corpo completo da requisição nem segredos.
import type {
APIGatewayProxyEvent,
APIGatewayProxyResult,
} from "aws-lambda";
import {
GetSecretValueCommand,
SecretsManagerClient,
} from "@aws-sdk/client-secrets-manager";
const secrets = new SecretsManagerClient({});
let cachedConfig: Record<string, string> | undefined;
async function loadConfig(): Promise<Record<string, string>> {
if (cachedConfig) return cachedConfig;
const secretArn = process.env.SECRET_ARN;
if (!secretArn) throw new Error("SECRET_ARN is not configured");
const result = await secrets.send(
new GetSecretValueCommand({ SecretId: secretArn }),
);
cachedConfig = JSON.parse(result.SecretString ?? "{}");
return cachedConfig;
}
function json(statusCode: number, body: unknown): APIGatewayProxyResult {
return {
statusCode,
headers: {
"content-type": "application/json",
"cache-control": "no-store",
},
body: JSON.stringify(body),
};
}
export async function handler(
event: APIGatewayProxyEvent,
): Promise<APIGatewayProxyResult> {
try {
if (event.httpMethod === "GET" && event.path.endsWith("/v1/health")) {
return json(200, {
ok: true,
stage: process.env.STAGE ?? "dev",
});
}
if (event.httpMethod === "POST" && event.path.endsWith("/v1/contact")) {
const body = JSON.parse(event.body ?? "{}") as {
email?: string;
message?: string;
};
if (!body.email || !body.message) {
return json(400, { ok: false, message: "email and message required" });
}
const config = await loadConfig();
const emailDomain = body.email.split("@")[1] ?? "unknown";
console.log(
JSON.stringify({
event: "contact_received",
emailDomain,
messageLength: body.message.length,
}),
);
return json(202, {
ok: true,
routedTo: config.supportQueue ?? "manual",
});
}
return json(404, { ok: false, message: "not found" });
} catch (error) {
console.error("handler_error", error);
return json(500, { ok: false, message: "internal error" });
}
}
Implemente o stack CDK
Substitua lib/small-api-stack.ts. Os pontos críticos são appSecret.grantRead(handler), retenção de logs, reserved concurrency, throttling e dataTraceEnabled: false para não registrar corpos de requisição em produção.
import * as cdk from "aws-cdk-lib";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as iam from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import * as logs from "aws-cdk-lib/aws-logs";
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
import { Construct } from "constructs";
import * as path from "path";
export class SmallApiStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const appSecret = secretsmanager.Secret.fromSecretNameV2(
this,
"AppSecret",
"prod/claude-code-demo/api",
);
const handler = new nodejs.NodejsFunction(this, "ApiHandler", {
functionName: "claude-code-small-api-prod",
entry: path.join(__dirname, "../lambda/handler.ts"),
handler: "handler",
runtime: lambda.Runtime.NODEJS_20_X,
architecture: lambda.Architecture.ARM_64,
memorySize: 256,
timeout: cdk.Duration.seconds(10),
logRetention: logs.RetentionDays.ONE_MONTH,
reservedConcurrentExecutions: 20,
environment: {
STAGE: "prod",
SECRET_ARN: appSecret.secretArn,
},
bundling: {
minify: true,
sourceMap: true,
externalModules: ["@aws-sdk/*"],
},
});
appSecret.grantRead(handler);
handler.addToRolePolicy(
new iam.PolicyStatement({
actions: ["cloudwatch:PutMetricData"],
resources: ["*"],
conditions: {
StringEquals: {
"cloudwatch:namespace": "ClaudeCodeLab/SmallApi",
},
},
}),
);
const api = new apigateway.RestApi(this, "SmallApi", {
restApiName: "claude-code-small-api",
cloudWatchRole: true,
deployOptions: {
stageName: "prod",
metricsEnabled: true,
loggingLevel: apigateway.MethodLoggingLevel.INFO,
dataTraceEnabled: false,
throttlingRateLimit: 20,
throttlingBurstLimit: 40,
},
});
const v1 = api.root.addResource("v1");
v1.addResource("health").addMethod(
"GET",
new apigateway.LambdaIntegration(handler),
);
v1.addResource("contact").addMethod(
"POST",
new apigateway.LambdaIntegration(handler),
{ apiKeyRequired: true },
);
const apiKey = api.addApiKey("ClientApiKey", {
apiKeyName: "claude-code-small-api-prod-client",
});
const usagePlan = api.addUsagePlan("BasicUsagePlan", {
throttle: { rateLimit: 10, burstLimit: 20 },
quota: { limit: 1000, period: apigateway.Period.MONTH },
});
usagePlan.addApiKey(apiKey);
usagePlan.addApiStage({ stage: api.deploymentStage });
new cdk.CfnOutput(this, "ApiUrl", { value: api.url });
}
}
Atualize também o arquivo de entrada em bin/.
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";
import { SmallApiStack } from "../lib/small-api-stack";
const app = new cdk.App();
new SmallApiStack(app, "SmallApiProdStack", {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION ?? "sa-east-1",
},
});
Revise o diff antes do deploy
O bootstrap do CDK é necessário na primeira vez em uma conta e região.
export AWS_REGION=sa-east-1
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
npx cdk bootstrap "aws://${AWS_ACCOUNT_ID}/${AWS_REGION}"
npm test
npx cdk synth
npx cdk diff SmallApiProdStack
npx cdk deploy SmallApiProdStack --require-approval never
Peça ao Claude Code para explicar o cdk diff, principalmente mudanças de IAM. Se uma permissão não tiver justificativa clara, ela não deve ir para produção sem revisão humana.
Teste a API e leia logs
Pegue a URL no output do CloudFormation e teste as rotas.
API_URL=$(aws cloudformation describe-stacks \
--stack-name SmallApiProdStack \
--query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" \
--output text)
curl "${API_URL}v1/health"
KEY_ID=$(aws apigateway get-api-keys \
--name-query claude-code-small-api-prod-client \
--query "items[0].id" \
--output text)
API_KEY=$(aws apigateway get-api-key \
--api-key "$KEY_ID" \
--include-value \
--query "value" \
--output text)
curl -X POST "${API_URL}v1/contact" \
-H "content-type: application/json" \
-H "x-api-key: ${API_KEY}" \
-d '{"email":"masa@example.com","message":"AWS deployment consultation"}'
Acompanhe os logs da Lambda:
aws logs tail "/aws/lambda/claude-code-small-api-prod" \
--since 1h \
--follow
CloudWatch Logs pode demorar alguns minutos. Um pequeno atraso não significa que o deploy falhou.
Deploy com GitHub Actions e OIDC
Não salve AWS Access Keys no GitHub Secrets. Crie um OIDC provider e uma role de deploy na AWS, limitando o trust policy ao repositório e branch corretos.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"
}
}
}
]
}
.github/workflows/deploy-aws.yml:
name: deploy-aws-cdk
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
id-token: write
contents: read
concurrency:
group: prod-aws-cdk
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-cdk-deploy-prod
aws-region: sa-east-1
- run: npm ci
- run: npm test
- run: npx cdk synth
- run: npx cdk diff SmallApiProdStack
- run: npx cdk deploy SmallApiProdStack --require-approval never
A policy da role de deploy depende do modelo de CDK bootstrap, da role de execução do CloudFormation e das regras da organização. Evite AdministratorAccess em produção. O caminho prático é restringir o OIDC, usar permission boundaries quando necessário e reduzir permissões com IAM Access Analyzer.
Adicione guardrails de custo
Uma API serverless pequena também gera custo se entrar em loop, receber spam ou escrever logs demais. O stack inclui throttling, usage plan e reserved concurrency. Adicione AWS Budgets antes da produção.
{
"BudgetName": "small-api-monthly-guardrail",
"BudgetLimit": {
"Amount": "20",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST"
}
[
{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "owner@example.com"
}
]
}
]
aws budgets create-budget \
--account-id "$AWS_ACCOUNT_ID" \
--budget file://budget.json \
--notifications-with-subscribers file://notifications-with-subscribers.json
Budgets e notificações podem não aparecer imediatamente. Configure antes do lançamento.
Rollback e falhas comuns
Para o primeiro serviço Lambda + API Gateway, o rollback mais simples costuma ser reverter o commit ruim e redeployar.
git revert <bad-commit-sha>
git push origin main
Depois confira API, eventos do CloudFormation e logs.
curl "${API_URL}v1/health"
aws cloudformation describe-stack-events \
--stack-name SmallApiProdStack \
--max-items 20
aws logs tail "/aws/lambda/claude-code-small-api-prod" --since 30m
Três falhas aparecem com frequência: alguém muda recursos no console depois do CDK, segredos aparecem em env vars ou logs, ou API Gateway registra corpos de requisição em produção. O stack usa dataTraceEnabled: false, mas o hábito de revisão continua obrigatório.
Peça uma revisão pré-deploy
Use Claude Code como revisor, exigindo evidência.
Faça uma revisão pré-deploy de AWS.
Verifique:
- Se o CDK diff adiciona wildcards IAM excessivos
- Se Lambda lê segredos apenas do Secrets Manager
- Se API Gateway tem throttling, usage plan e logging
- Se CloudWatch Logs pode expor dados pessoais ou bodies completos
- Se passos de rollback estão documentados
- Se npm test, cdk synth e cdk diff passaram
Retorne uma tabela com severity, file, line e fix.
Claude Code não é o aprovador final de produção. Fronteiras de conta, custo e exceções de segurança continuam com humanos. Ele serve para tornar a revisão repetível.
Resumo
O valor de Claude Code em deploy AWS não é apenas escrever CDK mais rápido. É conectar arquitetura, IaC, CI/CD, IAM, segredos, logs, rollback e custo em um fluxo que a equipe consegue repetir.
Para uma API pequena, Lambda + API Gateway + CDK geralmente basta. Use ECS/Fargate quando realmente precisar de contêiner sempre ativo. Use S3 + CloudFront ou Amplify quando o workload for principalmente frontend estático. O primeiro limite deve ser pequeno, revisável e reversível.
Se sua equipe quer adaptar regras de Claude Code, CDK, GitHub Actions OIDC, IAM mínimo e checks operacionais a um repositório real, agende uma consultoria de Claude Code. Masa pode revisar o repositório e o histórico de deploys AWS para transformar isso em um plano implementável.
Na prática, uma API de captura de leads como esta pode ficar deployável em meio dia a um dia se a conta AWS já estiver pronta. O ponto sensível não é o código Lambda, mas IAM, segredos, rollback e visibilidade de custos. Deixe Claude Code acelerar a implementação; mantenha a responsabilidade humana sobre o risco de produção.
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.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.