Get All Items from DynamoDB in Node.js (AWS SDK v3)

Reading a whole table in SDK v3 means paginating a Scan to the end. Each response caps at 1 MB, and you feed LastEvaluatedKey back as ExclusiveStartKey until one stops coming back (how DynamoDB cursors work).

The loop below is written by hand so the cursor is visible. In real code you would reach for paginateScan, which the SDK already ships.

Code

import {DynamoDBClient, ScanCommand} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

const items = [];
let lastEvaluatedKey;

do {
  const response = await client.send(
    new ScanCommand({
      TableName: 'Music',
      ExclusiveStartKey: lastEvaluatedKey
    })
  );

  items.push(...(response.Items ?? []));
  lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);

console.log(`Table holds ${items.length} items`);

Explanation

  • paginateScan already does thisimport {paginateScan} from '@aws-sdk/client-dynamodb', then for await (const page of paginateScan({client}, {TableName: 'Music'})). It is generated from the same three cursor fields the loop above uses by hand (ExclusiveStartKey, LastEvaluatedKey, Limit), so nothing changes behaviour when you switch.
  • Only an absent LastEvaluatedKey means done — a response with zero Items and a cursor is normal, not an empty table. Breaking on Items.length === 0 is the classic missing-rows bug, and a FilterExpression makes empty pages routine rather than rare.
  • Limit counts items evaluated per call, not items total — it is the third field the paginator drives, and neither it nor the paginator's pageSize bounds the size of the array you end up holding.
  • ExclusiveStartKey: undefined on the first pass is fine — the serializer drops undefined members, so the first iteration needs no special case.
  • items grows to the size of the table — process each page inside the loop and let it go (write, stream, aggregate) unless you know the table is small. Accumulating is one table growth away from an out-of-memory crash.
  • A scan bills every byte it reads, on every runProjectionExpression shrinks what crosses the wire and not the bill (why), and a FilterExpression drops items after they are read and charged (Scan with a filter). On a hot path you want a Query.
  • Split it with Segment / TotalSegments — N async workers, each driving its own cursor over its own slice, all on one shared client. Node will happily run them concurrently; the read cost does not change, only the wall clock (when that is worth it).

Do it visually

The DynamoDB query builder generates this entire program, pagination loop included, from a form, in SDK v3 and seven other targets.

DynoTable pages through a live table for you in an infinite-scrolling grid, and exports the Scan behind that grid as runnable code. Download DynoTable.

References

Last verified 2026-07-28 against the official AWS documentation linked above.

Build this request visually

Compose this operation in the free DynamoDB Query Builder — key condition, filter, index, Limit, sort order, and a pagination loop — and copy it back as a runnable SDK v3, CLI, or boto3 program.

Open the DynamoDB Query Builder

Work with DynamoDB without the Console

A fast DynamoDB desktop client that runs the real SQL DynamoDB can’t — JOINs, GROUP BY, aggregates — with visual editing and an AI agent on your own Bedrock keys.

Free 30-day trial, no credit card — then the Free plan with no time limit.