Claude Code × AWS Lambda Guía Completa | De la Generación de Funciones a la Automatización del Despliegue
Crea AWS Lambda con Claude Code: Node.js 24, SAM, IAM, API Gateway, S3, logs y errores comunes.
¿Has tenido estas experiencias al desarrollar con AWS Lambda? Las definiciones de tipo para los handlers son tediosas, tienes que buscar las políticas IAM cada vez, olvidaste cómo escribir las plantillas SAM… Claude Code resuelve todo esto de una vez.
Desde la implementación de funciones Lambda hasta la generación de políticas IAM, las pruebas locales y el despliegue en producción — cubrimos cada paso del desarrollo ultrarrápido de AWS Lambda con Claude Code usando ejemplos de código reales.
¿Por Qué Claude Code × AWS Lambda?
Las “partes tediosas” del desarrollo Lambda son casi en su totalidad código repetitivo (boilerplate).
- Definiciones de tipo para funciones handler (APIGatewayProxyHandler, S3Handler …)
- Manejo de errores y formatos de respuesta
- Diseño de políticas IAM de mínimo privilegio
- Escritura de plantillas SAM / CloudFormation
- Configuración del entorno de pruebas local
Claude Code genera todo esto con una sola frase como “Quiero una Lambda que haga X”. Combinado con AWS CLI y SAM CLI, puedes ejecutar todo desde la generación de código hasta el despliegue de una sola vez.
Configuración del Entorno
# Verificar herramientas necesarias
aws --version # AWS CLI v2
sam --version # SAM CLI 1.100+
node --version # Node.js 24+
# Configurar credenciales de AWS (si aún no están configuradas)
aws configure
# → Access Key ID, Secret Access Key, Region (us-east-1), Output (json)
<!-- Agregar a CLAUDE.md -->
## Configuración AWS
- Región predeterminada: us-east-1
- Runtime de Lambda: nodejs24.x
- Herramienta de despliegue: AWS SAM
- Directorio de código fuente: src/functions/
- Plantilla SAM: template.yaml
- Nombre del stack: my-app-{dev|staging|prod}
## Lineamientos de Política IAM
- Seguir estrictamente el principio de mínimo privilegio
- No usar comodines (*)
- Especificar los ARN de recursos de forma concreta
Ejemplo 1: API Gateway + Lambda (REST API)
El patrón más fundamental — una Lambda que recibe peticiones HTTP y las procesa.
Instrucciones para Claude Code
claude -p "
Cuando llegue una petición GET a /users/{userId},
recuperar la información del usuario de la tabla Users en DynamoDB y devolverla.
Implementar la función Lambda en TypeScript.
- Runtime: Node.js 24
- Nombre de tabla: UsersTable (recibido mediante variable de entorno)
- Manejo de errores: devolver respuestas 404/500 apropiadas
- Definiciones de tipo: usar @types/aws-lambda
- Salida a: src/functions/getUser/index.ts
"
Implementación Generada
// 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" });
}
};
La Plantilla SAM También Se Genera Automáticamente
# template.yaml (fragmento)
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
Ejemplo 2: Lambda con Trigger de Evento S3
Una Lambda que se activa con la carga de archivos para ejecutar procesamientos.
// 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 el prefijo thumbnails/ (prevenir bucle 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 creada: s3://${bucket}/${thumbnailKey}`);
};
Ejemplo 3: Lambda Programada (EventBridge)
# Configuración de EventBridge en 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 = CDMX 18:00 / Buenos Aires 21:00
Dejar que Claude Code Diseñe las Políticas IAM
claude -p "
Generar una política IAM de mínimo privilegio en JSON para una Lambda que necesita:
- GetObject del bucket S3 my-uploads
- PutItem/UpdateItem en la tabla DynamoDB ProcessingJobs
- SendMessage a la cola SQS ProcessingQueue
- Escribir en CloudWatch Logs
Inferir los ARN específicos a partir de los nombres de recursos proporcionados.
"
{
"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:us-east-1:*:table/ProcessingJobs"
},
{
"Effect": "Allow",
"Action": ["sqs:SendMessage"],
"Resource": "arn:aws:sqs:us-east-1:*:ProcessingQueue"
},
{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
}
]
}
Pruebas Locales y Despliegue en Producción
# Compilar
sam build
# Iniciar API localmente
sam local start-api --port 3001
# Invocación de prueba única
sam local invoke GetUserFunction --event events/get-user.json
# Ejecutar todo con Claude Code
claude -p "
Ejecutar sam build,
verificar resultados con sam local invoke GetUserFunction --event events/test-get-user.json.
Si todo está bien, ejecutar sam deploy --config-env dev.
"
Los 5 Errores Más Comunes
1. Inicialización que ignora los arranques en frío (cold starts)
// ❌ Crear el cliente dentro del handler en cada invocación
export const handler = async () => {
const ddb = new DynamoDBClient({}); // ← se instancia en cada invocación
};
// ✅ Inicializar una vez en el ámbito del módulo
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler = async () => { /* reutilizar ddb */ };
2. Dejar el timeout en el valor predeterminado (3 segundos) Para DynamoDB + APIs externas, establece al menos 10-30 segundos. Siempre configura según los requisitos reales de procesamiento.
3. Escribir secretos directamente en variables de entorno
# ❌ Codificado directamente en la plantilla
Environment:
Variables:
DB_PASSWORD: "my-secret"
# ✅ A través de Secrets Manager
Environment:
Variables:
DB_PASSWORD: !Sub "{{resolve:secretsmanager:myapp/db-password}}"
4. Retrasos de arranque en frío con Lambda en VPC Colocar una Lambda dentro de una VPC para conectividad con RDS agrega varios segundos al arranque en frío. Solucionar con Provisioned Concurrency o RDS Proxy.
5. Paquetes de despliegue sobredimensionados
Empaquetar node_modules junto puede alcanzar el límite de 250 MB. Mover las bibliotecas compartidas a un Lambda Layer.
Resumen
| Tarea | Contribución de Claude Code |
|---|---|
| Implementación del handler | Generar definiciones de tipo, manejo de errores y lógica de una sola vez |
| Plantilla SAM | Salida automática de eventos, IAM y variables de entorno |
| Política IAM | Generar con precisión diseños de mínimo privilegio |
| Pruebas locales | Automatizar la ejecución de sam invoke y la evaluación de resultados |
| Despliegue | Ejecutar build + deploy como un flujo de trabajo unificado |
Claude Code se encarga de las partes más laboriosas del desarrollo Lambda — definiciones de tipo y escritura de plantillas. Concentrarse en la lógica de negocio puede multiplicar la velocidad de implementación entre 3 y 5 veces.
Artículos Relacionados
- Claude Code × AWS S3 Automatización de Operaciones
- Claude Code × AWS DynamoDB Diseño de Esquemas
- Guía Completa de Mejores Prácticas de Seguridad con Claude Code
Cuándo encaja Lambda y cuándo no
Lambda encaja en trabajo corto, orientado a eventos y seguro de reintentar: API de pedidos, procesamiento de imágenes tras S3, reportes diarios con EventBridge y webhooks de Stripe o GitHub. No encaja bien en workers largos, conexiones persistentes, modelos grandes calientes o WebSocket con mucho estado. Pide a Claude Code razones a favor y en contra antes de generar código.
Términos en lenguaje simple
| Term | Plain meaning |
|---|---|
| handler | The function Lambda calls. API Gateway passes an HTTP event; S3 passes an object event. |
| event | The JSON payload given to Lambda. API Gateway, S3, and EventBridge shapes are different. |
| least privilege | Grant only the exact actions and resources the function needs. |
| cold start | The slower first run when Lambda creates a new execution environment. |
| idempotency | The same event can run twice without duplicate payment, email, or database writes. |
Unit test copiable 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);
});
});
Separar eventos de API Gateway, S3 y EventBridge
API Gateway necesitastatusCode ybody. S3 lee bucket/key desdeRecords. EventBridge suele usarsource, detail-type y detail. Nombra el trigger exacto en el prompt: HTTP API v2, S3 ObjectCreated o EventBridge schedule.
Variables, Secrets Manager e IAM de mínimo privilegio
Usa variables para configuración comoUSERS_TABLE yAPP_STAGE. API keys, passwords y secretos de webhook van en Secrets Manager; Lambda recibe solo el ARN. IAM debe usar acciones y ARN concretos.
CloudWatch Logs, reintentos e idempotencia
CloudWatch Logs es el primer lugar de diagnóstico. Si no hay logs, revisa región, función, permisos del rol y stack. S3, EventBridge e invocaciones asíncronas pueden reintentarse; usa IDs como claves de idempotencia.
Prompt de revisión 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 monetización, formación y consultoría
ClaudeCodeLab ofrece formación y consultoría para Lambda, IAM, SAM, auditoría de logs y gates de revisión. Empieza con PDF gratis y Gumroad; equipos deberían usar formación y consultoría para permisos, approvals y ruta de ingresos.
Resultado práctico
Separé los ejemplos en handler y tests para verificarlos connpm test. No ejecutésam deploy real porque depende de cuenta, región, ARN y tabla. En producción registrasam validate --lint, sam build, sam local invoke, logs e IAM diff.
Enlaces oficiales adicionales
- Lambda runtimes
- Building Lambda functions with Node.js
- Working with Lambda environment variables
- Security best practices in IAM
- Sending Lambda function logs to CloudWatch Logs
- Invoking Lambda with API Gateway
- Using an S3 trigger to invoke Lambda
- Retries and failures in Lambda applications
Checklist de enlaces internos
- guía AWS IAM
- guía AWS API Gateway
- guía AWS S3
- guía AWS CloudWatch
- guía de funciones serverless
- buenas prácticas de seguridad
Referencias
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Workflow de Obsidian a CLAUDE.md con Claude Code
Convierte notas de trabajo de Obsidian en notas operativas de CLAUDE.md para no repetir contexto.
Claude Code Revenue CTA Routing: de artículos a PDF, Gumroad y consulta
Un flujo con Claude Code para dirigir lectores a PDF gratis, Gumroad o consulta según intención.
Reglas de handoff para equipos con Claude Code: evidencia, permisos, rollback e ingresos
Formato práctico para entregar trabajo de Claude Code con pruebas, permisos, rollback, PDF gratis, Gumroad y consulta.