DEV Community

Cover image for DynamoDB Batch Operations: BatchGetItem & BatchWriteItem
DynoTable
DynoTable

Posted on • Originally published at dynotable.com

DynamoDB Batch Operations: BatchGetItem & BatchWriteItem

When you need to read or write many items at once, firing one GetItem or PutItem
per item means one network round trip per item — slow, and chatty. DynamoDB's batch
APIs fold many item operations into a single request: BatchGetItem for reads,
BatchWriteItem for writes.

They're a throughput-and-latency win, not a consistency guarantee — and that
distinction is where people get burned. A batch is not a transaction.

What are DynamoDB batch operations?

DynamoDB batch operations fold many item reads or writes into a single request: BatchGetItem fetches up to 100 items, BatchWriteItem puts or deletes up to 25, each capped at 16 MB. They save round trips, not capacity. Critically, a batch is not a transaction — items succeed or fail independently, with no rollback.

  • BatchGetItem — fetch up to 100 items (or 16 MB) across one or more tables in one call.
  • BatchWriteItem — up to 25 put/delete operations (or 16 MB) in one call. No updates — puts and deletes only.
  • Not atomic. Individual items can succeed while others fail. There's no rollback.
  • Partial failure is normal. Throttled items come back in UnprocessedItems / UnprocessedKeys — you must retry them yourself, with backoff.
  • Same capacity cost as the individual calls — batching saves round trips, not capacity units.

The problem: many items, one round trip

Say you run a support desk. A dashboard needs to load 50 tickets by ID to render a
queue; an overnight job archives 1,000 resolved tickets. Doing that one item at a time
is 50 (or 1,000) sequential round trips — latency stacks up and the job crawls.

Batching collapses those into a handful of calls. The 50-ticket read becomes a single
BatchGetItem; the archive job becomes a stream of BatchWriteItem calls of 25
deletes each. Far fewer round trips, the same data moved.

How the batch APIs work

BatchGetItem takes a set of primary keys (across one or more tables) and returns
the matching items. You can request strongly consistent reads per table. Anything it
couldn't read — usually because the request brushed a throughput limit — comes back in
UnprocessedKeys rather than failing the whole call.

BatchWriteItem takes a list of PutRequest / DeleteRequest operations. Note
what's missing: there is no update. A batch write either replaces a whole item
(put) or removes it (delete) — to modify specific attributes you still need
UpdateItem. Items it couldn't write come back in UnprocessedItems.

DynamoDB Batch Operations: BatchGetItem & BatchWriteItem

The key mental model: a batch is a bundle of independent operations, each
succeeding or failing on its own — not one all-or-nothing unit.

Batches are not transactions

This is the trap. If your archive job's batch hits a throughput limit halfway, some
tickets are deleted and some aren't — and DynamoDB does not undo the ones that
went through. There's no rollback, no isolation, no "all 25 or none."

If you need all-or-nothing semantics — "move the ticket to archived and decrement
the open-tickets counter, or do neither" — that's
TransactWriteItems, not a batch. Transactions cost
more (each operation is billed double) and cap at 100 items, but they give you the
atomicity batches deliberately don't.

Handling unprocessed items

A correct batch caller always checks the unprocessed set and retries it. DynamoDB
returns UnprocessedItems/UnprocessedKeys whenever the request as a whole was
accepted but some items couldn't be served — typically transient throttling.

Re-submit only the unprocessed items, with
exponential backoff and jitter.
Treating a batch as fire-and-forget silently drops writes — the kind of bug that
surfaces months later as missing data.

Batch writes in DynoTable

Estimate what a bulk job will cost first with the
DynamoDB pricing calculator — a batch consumes the
same capacity as the individual writes it bundles, just in fewer requests.

In DynoTable, you stage your edits locally and review them before committing them —
bulk changes across many rows go out as grouped requests rather than one API call
each. Bulk deletes go out as batched writes, with the unprocessed-item retry handled
for you.

Reviewing staged edits before committing them as a batch in DynoTable.

Pitfalls + next steps

  • Always retry UnprocessedItems/UnprocessedKeys with backoff — they're expected, not exceptional.
  • No partial-failure rollback. Need atomicity? Use transactions.
  • No updates in a batch writeBatchWriteItem is put/delete only; reach for UpdateItem to change attributes.
  • Mind the per-call caps — 25 writes / 100 reads / 16 MB. Exceeding them fails the whole call with a ValidationException (too many items in BatchGetItem, in BatchWriteItem). Page through larger jobs; see pagination.

Want to run bulk reads and writes without scripting the retry loop?
Download DynoTable and edit your tables directly.

Top comments (0)