SDK v3 Fundamentals Best Practices
These are the habits that make AWS SDK for JavaScript v3 code small, typed, and cheap to run.
Busca en todas las páginas de la documentación
These are the habits that make AWS SDK for JavaScript v3 code small, typed, and cheap to run.
They are specific to v3's design: the command pattern, per-service packages, and the middleware stack all reward a particular discipline. Walk the list once, then use it as a review checklist before shipping.
import { GetObjectCommand } from "@aws-sdk/client-s3" let the bundler drop every command you never reference.import * as AWS. A namespace import defeats tree-shaking by pulling the whole client surface into the bundle.@aws-sdk/client-<service> per service rather than reaching for a monolith - there is no v3 monolith anyway.aws-sdk. It is in maintenance mode and cannot tree-shake; use the modular @aws-sdk/* packages.Named command imports are what make v3 bundles small.
// Good: only ListBucketsCommand is reachable and bundled.
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: "us-east-1" });
await s3.send(new ListBucketsCommand({}));S3Client and a DynamoDBClient separately; do not try to share one across services.import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
// Module scope: constructed once, reused by every warm invocation.
const ddb = new DynamoDBClient({ region: "us-east-1" });
export async function handler(/* ... */) {
// reuse ddb here
}GetObjectCommandInput/Output when you build inputs in helpers, instead of any.undefined; use ?? [] and optional chaining.as any on a command input hides real mistakes the compiler would catch.import { GetObjectCommand, type GetObjectCommandInput } from "@aws-sdk/client-s3";
function buildGet(input: GetObjectCommandInput) {
return new GetObjectCommand(input); // typo in a key is a compile error
}instanceof NoSuchKey (and friends) rather than string-comparing messages.$metadata.requestId on failure. It is the id AWS support needs to trace a specific call.maxAttempts and the retry mode in client config for bursty workloads instead of hand-rolling loops.import { GetObjectCommand, NoSuchKey } from "@aws-sdk/client-s3";
try {
await s3.send(new GetObjectCommand({ Bucket: "b", Key: "missing" }));
} catch (err) {
if (err instanceof NoSuchKey) return null;
console.error((err as { $metadata?: { requestId?: string } }).$metadata?.requestId);
throw err;
}fromCognitoIdentityPool, never static keys a user can read from the bundle.fromEnv/fromIni to pin the source in CI or multi-account local setups.region (or AWS_REGION) so calls do not depend on ambient defaults.@aws-sdk/* on one version. Mismatched versions can duplicate shared internals and cause subtle breakage.name so you can remove it.fetch it.Named command imports let the bundler tree-shake everything you do not use. A import * as AWS namespace import pulls the whole client surface in and defeats that.
Client construction sets up connection pools and configuration. Rebuilding one per call wastes CPU and sockets, so build it once and reuse it across requests.
At module scope, outside the handler. Warm invocations then reuse the same client instead of constructing a new one on every request.
Match typed exception classes with instanceof, such as NoSuchKey, and read err.$metadata.requestId for logging. Avoid comparing error message strings.
Usually no. v3 retries throttling and transient errors with backoff by default. Tune maxAttempts and the retry mode instead of reimplementing retries.
Mismatched versions can pull duplicate copies of shared internals and cause subtle incompatibilities. Update every @aws-sdk/* package together.
From scoped, temporary credentials via fromCognitoIdentityPool, or not at all - use a presigned URL. Never embed static keys a user can read.
Only for cross-cutting needs like logging, tracing, or custom headers. Add it by name so you can remove it, and keep it light since it runs on every call.
No. The @aws-sdk/client-* packages ship their own types. Import the generated input/output types directly instead of using any.
A namespace import or an unused broad import. Import only the specific commands you call so the rest is tree-shaken out.
Ambient region defaults differ across machines and runtimes. Pinning the region makes behavior reproducible and avoids calls silently going to the wrong region.
Only for maintaining existing v2 code. It is in maintenance mode and cannot tree-shake, so start anything new on the modular v3 packages.
Stack versions: This page was written for the AWS SDK for JavaScript v3 on Node.js 18+ (and boto3 1.43.x / Python 3.10+ where contrasted).
Revisado por Chris St. John·Última actualización: 23 jul 2026