@aws-sdk v3
Usa clientes modulares de AWS SDK v3 en Lambdas y contenedores de Node.js: importa solo lo que necesites, configura el middleware una vez y reutiliza los clientes en varias invocaciones.
Receta
Tarjeta de receta de referencia rápida: lista para copiar y pegar.
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: process.env.AWS_REGION });
export async function getObjectText(bucket: string, key: string) {
const res = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
return await res.Body?.transformToString();
}Cuándo usarlo: Cualquier llamada a un servicio de AWS desde Node 24 o Lambda nodejs24.x. No añadas aws-sdk v2.
Ejemplo funcional
// src/aws/clients.ts
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand, PutCommand } from "@aws-sdk/lib-dynamodb";
import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm";
import { NodeHttpHandler } from "@smithy/node-http-handler";
const requestHandler = new NodeHttpHandler({
connectionTimeout: 3_000,
requestTimeout: 10_000,
});
const ddbDoc = DynamoDBDocumentClient.from(
new DynamoDBClient({ maxAttempts: 3, requestHandler }),
{ marshallOptions: { removeUndefinedValues: true } }
);
const ssm = new SSMClient({ maxAttempts: 3 });
export async function getOrder(id: string) {
const res = await ddbDoc.send(
new GetCommand({ TableName: process.env.TABLE_NAME!, Key: { id } })
);
return res.Item;
}
export async function putOrder(item: Record<string, unknown>) {
await ddbDoc.send(
new PutCommand({ TableName: process.env.TABLE_NAME!, Item: item })
);
}
let cachedApiKey: string | undefined;
export async function getApiKey() {
if (cachedApiKey) return cachedApiKey;
const res = await ssm.send(
new GetParameterCommand({ Name: "/prod/api/KEY", WithDecryption: true })
);
cachedApiKey = res.Parameter?.Value;
return cachedApiKey!;
}// src/handler.ts
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { getOrder } from "./aws/clients.js";
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
const id = event.pathParameters?.id!;
const order = await getOrder(id);
return {
statusCode: order ? 200 : 404,
body: JSON.stringify(order ?? { error: "not found" }),
};
};Lo que esto demuestra:
- Paquetes separados por servicio (
@aws-sdk/client-dynamodb,@aws-sdk/client-ssm) - Cliente de documento para mapas de atributos de JS simples
- Tiempos de espera de
NodeHttpHandlercompartidos y reutilización de clientes con ámbito de inicialización - Parámetro SSM almacenado en caché en el ámbito del módulo en invocaciones cálidas
Análisis profundo
v2 vs v3
| Aspecto | AWS SDK v2 | AWS SDK v3 |
|---|---|---|
| Importación | import AWS from "aws-sdk" | @aws-sdk/client-s3 |
| Tamaño del paquete | SDK completo | Tree-shakeable por servicio |
| API | .promise() | client.send(new Command()) |
| Middleware | Limitado | Pila de middleware de Smithy |
Patrón de comando
Cada operación es una clase de comando:
import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";
await sqs.send(new SendMessageCommand({
QueueUrl: process.env.QUEUE_URL!,
MessageBody: JSON.stringify({ orderId: "42" }),
}));Los comandos son inmutables; es seguro construirlos por solicitud.
Ejemplo de Middleware
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
s3.middlewareStack.add(
(next) => async (args) => {
const start = Date.now();
const result = await next(args);
console.log(JSON.stringify({ awsCall: args.request?.hostname, ms: Date.now() - start }));
return result;
},
{ step: "finalizeRequest", name: "logLatency" }
);Usa middleware para el registro transversal, no para la lógica de negocio.
Agrupación en tiempo de ejecución de Lambda
Los tiempos de ejecución de Node.js 18+ de Lambda incluyen AWS SDK para JavaScript v3. Puedes marcar @aws-sdk/* como external en esbuild para reducir el tamaño de los paquetes de despliegue. Fija las versiones del SDK en CI si dependes del comportamiento del SDK agrupado en tiempo de ejecución.
Cadena de credenciales
En Lambda, las credenciales provienen automáticamente del rol de ejecución. El desarrollo local utiliza un archivo de credenciales compartidas o SSO:
aws sso login --profile dev
AWS_PROFILE=dev npm run invoke:localErrores comunes
- Importar
@aws-sdk/client-s3y todolib-dynamodbsin usar - sigue siendo mejor que v2, pero audita las importaciones. Solución: un módulo cliente por dominio. - Nuevo cliente por solicitud - sobrecarga del handshake TLS. Solución: singleton con ámbito de módulo.
maxAttemptsfaltante en redes inestables - los 503 transitorios fallan las invocaciones. Solución:maxAttempts: 3por defecto suele ser suficiente; ajusta por servicio.GetObjectgrande en memoria - OOM en archivos grandes. Solución: transmiteBodya la carga de S3 o al disco.- Obtención de parámetros SSM en cada invocación - lento y limitado. Solución: caché con TTL en el ámbito del módulo.
- Desajuste de región -
PermanentRedirecten S3. Solución: establece laregionen el cliente o la variable de entornoAWS_REGION.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| @aws-sdk v3 modular | Por defecto para todas las llamadas a AWS | Nunca para código nuevo |
| AWS SDK v2 | Solo mantenimiento de legado | Nuevas Lambdas |
| AWS Data API | Aurora Serverless SQL sin VPC | Necesitas todas las características de PG |
| AWS CDK L2 constructs | Aprovisionamiento de infraestructura | Llamadas a S3/GetObject a nivel de aplicación |
Preguntas frecuentes
¿Necesitamos comprimir `node_modules/@aws-sdk`?
Para Lambda, puedes externalizar el SDK si usas un tiempo de ejecución gestionado que lo incluya. Para contenedores, instala solo los clientes que necesites en la imagen.
¿Cómo pagino?
Usa los ayudantes de paginación: import { paginateListObjectsV2 } from "@aws-sdk/client-s3" o itera sobre NextToken en los comandos.
¿Funciona v3 con el modo estricto de TypeScript?
Sí. Los tipos de entrada de comandos se generan a partir de modelos Smithy.
¿Qué hay de `@aws-sdk/client-sts` AssumeRole?
Crea un cliente STS, asume un rol, pasa las credenciales devueltas a los clientes de servicio a través de la configuración credentials para el acceso entre cuentas.
¿Cómo se relaciona esto con Secrets Manager?
El mismo patrón: @aws-sdk/client-secrets-manager + GetSecretValueCommand, almacenado en caché al inicio. Consulta Secrets Managers.
¿Puedo usar v3 en Express en ECS?
Rutas de código idénticas. El rol de tarea de IAM reemplaza el rol de ejecución de Lambda para las credenciales.
Relacionado
- Patrones de manejadores de Lambda - ámbito de inicialización del cliente
- Mitigación de arranque en frío - SDK externo en paquetes
- Secrets Managers - SSM y Secrets Manager
- Conceptos básicos de Serverless - configuración de Lambda
- Mejores prácticas de Serverless - lista de verificación de la sección
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.