AWS SDK for JavaScript v3 Bare-Bones vs Aggregated Client Styles: Production Best Practices
The AWS SDK for JavaScript v3 offers two distinct import styles: bare-bones (modular) clients that import only specific commands for minimal bundle sizes, and aggregated (v2-style) clients that bundle all service operations for convenience, with the bare-bones approach explicitly recommended for production serverless workloads.
The aws/agent-toolkit-for-aws repository provides authoritative guidance on AWS SDK for JavaScript v3 usage patterns within its core skills documentation. When migrating from v2 or optimizing Lambda functions, developers must choose between these two client styles, which present distinct trade-offs between deployment bundle size and API convenience.
Understanding the Two Client Styles
Bare-Bones (Modular) Clients
The bare-bones style represents the underlying Smithy-generated client architecture. In this pattern, you import the service client class alongside individual command classes, then invoke commands through the client.send() method. According to skills/core-skills/aws-sdk-js-v3-usage/SKILL.md (lines 26-34), this approach is explicitly recommended for production code because it enables aggressive tree-shaking, ensuring only imported commands appear in your final bundle.
Aggregated (v2-Style) Clients
The aggregated style provides a compatibility shim that mirrors the AWS SDK for JavaScript v2 API surface. When you import the aggregated client, you gain direct access to all service methods on the client instance (e.g., s3.getObject()). While this simplifies migration from v2, it pulls in the entire service API surface, increasing bundle size and cold-start latency regardless of which methods you actually invoke.
Bundle Size and Performance Impact
The architectural distinction between these styles directly impacts your deployment artifacts:
-
Bare-bones imports: Only the specific commands you import (e.g.,
GetObjectCommand) and their transitive dependencies are included. Unused commands are eliminated during tree-shaking, resulting in optimal bundle sizes for Lambda and containerized environments. -
Aggregated imports: The entire service API surface is bundled even if you only call one method. This convenience increases deployment package size and initialization overhead.
Both styles share identical configuration models—region, credentials, retry settings, and middleware work identically regardless of which client style you choose.
Implementation Examples
Bare-Bones Client (Production Recommended)
This pattern from the Agent Toolkit demonstrates the optimal bare-bones approach for S3 operations:
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: "us-east-1" });
const result = await s3.send(
new GetObjectCommand({ Bucket: "my-bucket", Key: "example.txt" })
);
// Consume the streaming body safely
const { Body } = result;
const text = await Body.transformToString();
Aggregated Client (Migration Convenience)
For teams transitioning from SDK v2, the aggregated style offers familiar method-per-operation calls:
import { S3 } from "@aws-sdk/client-s3";
const s3 = new S3({ region: "us-east-1" });
const { Body } = await s3.getObject({ Bucket: "my-bucket", Key: "example.txt" });
const text = await Body.transformToString();
DynamoDB Document Client (Aggregated Pattern)
The aggregated pattern also appears in higher-level document client abstractions, as documented in skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md:
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
const doc = DynamoDBDocument.from(new DynamoDBClient({ region: "us-east-1" }));
await doc.put({ TableName: "Users", Item: { id: "u1", name: "Alice" } });
const { Item } = await doc.get({ TableName: "Users", Key: { id: "u1" } });
Configuration and Import Best Practices
The Agent Toolkit's SKILL.md establishes several critical guidelines for SDK usage:
Import from Package Root
Always import from the package root rather than deep paths. According to lines 19-22 of skills/core-skills/aws-sdk-js-v3-usage/SKILL.md, avoid importing from internal paths like …/dist-cjs/S3Client. The correct import pattern is import { S3Client } from "@aws-sdk/client-s3".
Per-Client Configuration
Unlike AWS SDK v2, v3 has no global configuration. Lines 44-50 of the skill documentation emphasize that you must pass configuration objects to each client constructor. For cross-region calls, resolve credentials once and share them across client instances to leverage caching behavior (lines 73-79).
Avoid Mixed Imports
Never import both bare-bones and aggregated styles for the same service within a single file. Doing so imports duplicate symbols and defeats tree-shaking optimizations, resulting in unnecessarily large bundles with no performance benefit.
When to Use Each Style
Choose Bare-Bones When:
- Optimizing Lambda cold-start latency where bundle size directly impacts initialization time
- Deploying to containerized environments with strict memory or storage constraints
- Building production applications with modern bundlers (Webpack, Rollup, esbuild) that support tree-shaking
- Starting greenfield projects where performance takes precedence over migration convenience
Choose Aggregated When:
- Rapidly prototyping applications where bundle size is not a primary constraint
- Migrating legacy v2 codebases where refactoring hundreds of method calls is not feasible
- Maintaining internal tools or one-off scripts where startup time is irrelevant to the user experience
Summary
- Bare-bones clients import specific command classes alongside the client, enabling tree-shaking and minimal bundle sizes for serverless workloads
- Aggregated clients import the entire service API surface, offering v2-style convenience methods at the cost of larger bundles and slower initialization
- The
aws/agent-toolkit-for-awsrepository explicitly recommends bare-bones style for production code inskills/core-skills/aws-sdk-js-v3-usage/SKILL.md(lines 26-34) - Both styles use identical configuration patterns but must not be mixed in the same file to avoid duplicate symbols
- Always import from package roots, never from internal distribution paths like
dist-cjs
Frequently Asked Questions
What is the difference between bare-bones and aggregated clients in AWS SDK for JavaScript v3?
Bare-bones clients require importing individual command classes (e.g., GetObjectCommand) and invoking them via client.send(new Command()), while aggregated clients expose all service methods directly on the client instance (e.g., client.getObject()). The bare-bones approach supports tree-shaking and results in smaller bundles, whereas aggregated clients pull in the entire service API regardless of which methods you actually call.
Which AWS SDK for JavaScript v3 client style should I use for Lambda functions?
Use the bare-bones (modular) style for Lambda functions. According to the Agent Toolkit's SKILL.md (lines 26-34), this approach minimizes deployment package size and reduces cold-start latency by ensuring only imported commands are included in the bundle. The aggregated style increases bundle size and initialization time, which can negatively impact serverless performance and execution costs.
Can I mix bare-bones and aggregated client imports in the same file?
No, you should not mix these import styles for the same service within a single file. Doing so causes symbol duplication and defeats tree-shaking optimizations, resulting in larger bundles that include both the modular command classes and the aggregated client methods. Choose one style per service per file—either import specific commands or import the aggregated client, but never both.
How do I configure credentials when using bare-bones clients?
Pass credentials and region configuration directly to the client constructor, as AWS SDK v3 has no global configuration object. According to lines 44-50 of skills/core-skills/aws-sdk-js-v3-usage/SKILL.md, create a configuration object containing your region and credentials, then pass it to each client constructor. For applications making cross-region calls, resolve credentials once and share them across multiple client instances to leverage the SDK's internal caching mechanism (lines 73-79).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →