-
Notifications
You must be signed in to change notification settings - Fork 0
SDK v2 to v3 cheat sheet
The toolkit's v3 release coincides with the AWS SDK v2 → v3 migration. This page covers the SDK-level changes most consumers hit when upgrading. AWS's official guide has the canonical reference; this is the toolkit-flavored summary.
| v2 | v3 |
|---|---|
require('aws-sdk') (one mega-package) |
@aws-sdk/client-<service> per service + @aws-sdk/lib-<wrapper> for high-level wrappers |
AWS.DynamoDB |
import {DynamoDBClient} from '@aws-sdk/client-dynamodb' |
AWS.DynamoDB.DocumentClient |
import {DynamoDBDocumentClient} from '@aws-sdk/lib-dynamodb' |
AWS.DynamoDB.Converter |
import {marshall, unmarshall} from '@aws-sdk/util-dynamodb' |
Tree-shakable: only the Commands you import end up in your bundle.
// v2
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
const client = new AWS.DynamoDB.DocumentClient();
// v3
import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
import {DynamoDBDocumentClient} from '@aws-sdk/lib-dynamodb';
const baseClient = new DynamoDBClient({region: 'us-east-1'});
const client = DynamoDBDocumentClient.from(baseClient, {
marshallOptions: {removeUndefinedValues: true},
unmarshallOptions: {wrapNumbers: false}
});Region is passed at construction (no global AWS.config). Marshall options replace convertEmptyValues / convertClassInstanceToMap from v2.
// v2
client.get({TableName, Key}, (err, data) => ...);
const data = await client.get({TableName, Key}).promise();
// v3
import {GetCommand} from '@aws-sdk/lib-dynamodb';
const data = await client.send(new GetCommand({TableName, Key}));Every operation is a Command class. client.send(command) always returns a Promise. .promise() is gone.
DynamoDB Command class names from @aws-sdk/lib-dynamodb: GetCommand, PutCommand, UpdateCommand, DeleteCommand, QueryCommand, ScanCommand, BatchGetCommand, BatchWriteCommand, TransactGetCommand, TransactWriteCommand.
// v2 — manual loop
let lastKey;
do {
const data = await client.scan({...params, ExclusiveStartKey: lastKey}).promise();
process(data.Items);
lastKey = data.LastEvaluatedKey;
} while (lastKey);
// v3 — built-in async iterator
import {paginateScan} from '@aws-sdk/lib-dynamodb';
for await (const page of paginateScan({client}, params)) {
process(page.Items);
}The toolkit's iterateList / iterateItems provide an equivalent ergonomic surface that works against Query and Scan uniformly — see Mass operations.
Note: SDK paginators do not resubmit UnprocessedKeys / UnprocessedItems and they don't help with Limit-vs-FilterExpression short-page semantics. The toolkit's applyBatch / getBatch / paginateList handle those.
// v2 — implicit config; or AWS.SharedIniFileCredentials
AWS.config.credentials = new AWS.SharedIniFileCredentials({profile: 'staging'});
// v3 — explicit on the client
import {fromIni, fromNodeProviderChain} from '@aws-sdk/credential-providers';
const client = new DynamoDBClient({
region: 'us-east-1',
credentials: fromIni({profile: 'staging'})
});fromNodeProviderChain() is the default chain (env vars → SSO → profile → EC2 metadata → ECS task role).
@aws-sdk/lib-dynamodb middleware handles plain JS ↔ DynamoDB AttributeValues automatically — same idea as v2's DocumentClient.
| v2 quirk | v3 behavior |
|---|---|
| Empty strings: rejected by default | Allowed (DynamoDB has accepted them since 2020) |
undefined values: silently dropped |
Throws unless marshallOptions.removeUndefinedValues: true
|
Numbers > Number.MAX_SAFE_INTEGER: lossy |
Set unmarshallOptions.wrapNumbers: true to get NumberValue instances |
BigInt: not supported by Converter |
Round-trips as BigInt (note: JSON.stringify breaks on BigInt without a custom replacer) |
Sets via client.createSet([...])
|
Pass new Set([...]) — type detected from element types (strings → SS, numbers → NS, Uint8Array → BS) |
| Binary sets had marshalling bugs in early v3 | Cover round-trips of new Set([Uint8Array.of(...)]) in your tests |
The toolkit's Adapter requires a DynamoDBDocumentClient — you control marshall behavior at construction time.
v3 errors have a name field (the AWS error code) and a $metadata object with the response status:
try {
await adapter.put(item);
} catch (err) {
console.error(err.name); // e.g. 'ConditionalCheckFailedException'
console.error(err.$metadata.httpStatusCode); // e.g. 400
}The toolkit's REST handler maps error names to HTTP statuses via mapErrorStatus — see REST core.
-
AWS.configglobal — no replacement; pass options per client. -
'success'/'error'event emitters — Promises only. -
service.makeRequest()— no v3 equivalent; use Commands. -
AWS.util— internal v2 utility module; no v3 equivalent.
-
BatchWriteItem/BatchGetItemchunking +UnprocessedItemsretry →applyBatch/getBatch. -
TransactWriteItemsaction ceiling check →applyTransaction. -
Limit-vs-FilterExpressionshort-page accumulation →paginateList. -
BatchGetItemorder preservation →readOrderedListByKeys. - Sparse-GSI second-hop reads →
Adapter.indirectIndices. - Patch builder + atomic array ops →
expressions/buildUpdate.
These are not in the SDK. If you bypass the toolkit you'll need to build them yourself.
Start here
- Getting started
- Concepts
- Key and field design
- Compatibility
- Migration: v2 to v3
- SDK v2 to v3 cheat sheet
Guides
- Hierarchical data walkthrough
- Key expression patterns
- Multi-type tables
- Pagination
- Mass operation semantics
- URL schema design
Adapter
- Adapter
- Constructor options
- CRUD methods
- Mass methods
- Batch builders
- Hooks
- Raw marker
- Indirect indices
- Transaction auto-upgrade
Expression builders
Batch / transactions / mass / paths
REST surface
Framework adapters
Recipes
- Recipes index
- List records of a tier
- Per-tier sparse GSI markers
- Tier within a partition
- Reservation with auto-release
- Keys-only GSI, runtime projection
- Cascade subtree operations
- Querying subtrees with buildKey
- Filter URL grammar
- Text search
- Provisioning workflow
- Resumable mass operations
History