Skip to content

SDK v2 to v3 cheat sheet

Eugene Lazutkin edited this page Apr 18, 2026 · 2 revisions

SDK v2 → 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.

Imports

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.

Client construction

// 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.

Commands replace methods

// 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.

Paginators

// 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.

Credential providers

// 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).

Marshalling

@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.

Errors

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.

Removed v2 features

  • AWS.config global — 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.

What the toolkit handles for you

  • BatchWriteItem / BatchGetItem chunking + UnprocessedItems retry → applyBatch / getBatch.
  • TransactWriteItems action ceiling check → applyTransaction.
  • Limit-vs-FilterExpression short-page accumulation → paginateList.
  • BatchGetItem order 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.

Clone this wiki locally