Skip to content

Batch and transactions

Eugene Lazutkin edited this page Apr 16, 2026 · 7 revisions

Batch and transactions

dynamodb-toolkit/batch exports four chunkers + a backoff helper. All work with the same {action, params} descriptor shape that the Adapter's Adapter:-Batch-builders return.

import {applyBatch, applyTransaction, getBatch, getTransaction, backoff, TRANSACTION_LIMIT} from 'dynamodb-toolkit/batch';

applyBatch(client, ...descriptors)

Chunked BatchWriteItem (limit 25 per call) with UnprocessedItems retry + exponential backoff. Returns the count of items processed.

Accepts {action: 'put' | 'delete', params} descriptors as positional args, arrays of descriptors, or null (skipped).

const total = await applyBatch(client, [
  {action: 'put', params: {TableName: 'planets', Item: {name: 'A'}}},
  {action: 'delete', params: {TableName: 'planets', Key: {name: 'B'}}}
]);
// → 2

applyTransaction(client, ...descriptors)

Single TransactWriteItems call. No chunking — transactions are atomic. Throws if more than TRANSACTION_LIMIT (100) actions.

Accepts {action: 'check' | 'delete' | 'put' | 'patch', params} descriptors.

await applyTransaction(client, [
  {action: 'check', params: {TableName: 'planets', Key: {name: 'parent'}, ConditionExpression: 'attribute_exists(#k0)', ExpressionAttributeNames: {'#k0': 'name'}}},
  {action: 'put', params: {TableName: 'planets', Item: {name: 'child', parent: 'parent'}}}
]);

getBatch(client, ...descriptors)

Chunked BatchGetItem (limit 100 per call) with UnprocessedKeys retry. Returns Array<{table, item}>.

const results = await getBatch(client, [
  {action: 'get', params: {TableName: 'planets', Key: {name: 'Hoth'}}},
  {action: 'get', params: {TableName: 'planets', Key: {name: 'Bespin'}}}
]);
// → [{table: 'planets', item: {...}}, {table: 'planets', item: {...}}]

getTransaction(client, ...descriptors)

Single TransactGetItems call (max 100 items). Returns Array<{table, item, adapter?}> preserving call order, with null items for misses. The adapter field passes through whatever you put on the descriptor — useful for routing results back to per-table revivers.

const results = await getTransaction(client,
  {action: 'get', params: {TableName: 'planets', Key: {name: 'Hoth'}}, adapter: planetsAdapter},
  {action: 'get', params: {TableName: 'moons', Key: {planet: 'Endor', name: 'Sanctuary'}}, adapter: moonsAdapter}
);

backoff(from?, to?, finite?)

Generator yielding exponential delays with full jitter. Default base 50ms, cap 2s. With finite=true, stops after a fixed number of yields.

for (const ms of backoff(50, 2000, true)) {
  await trySomething();
  if (succeeded) break;
  await sleep(ms);
}

TRANSACTION_LIMIT

The DynamoDB cap on TransactWriteItems actions per call: 100. v2 used 25 (the old limit); v3 raised it to match the current SDK.

UnprocessedItems retry semantics

The SDK does not automatically resubmit UnprocessedItems / UnprocessedKeys. The toolkit's applyBatch and getBatch loop on the unprocessed remnant with exponential backoff between attempts. ProvisionedThroughputExceededException is also caught and retried; other errors propagate.

If you need different retry behavior, build with the lower-level helpers (batchWrite / batchGet from inside the package) or write your own loop using backoff.

Clone this wiki locally