dynobase-icon
Dynobase

DynamoDB Pagination: LastEvaluatedKey and Paginators

Ashan Fernando

Written by Ashan Fernando

Last updated: October 23rd, 2026

Rewriting the same filters again and again? Dynobase builds filters visually, with operators for real-world data, and saves parameterized favorites that ask for values when you run them. Filters and favorites in Dynobase

DynamoDB paginates Query and Scan results with a continuation key. Pass the response's LastEvaluatedKey unchanged as the next request's ExclusiveStartKey, and stop when that key is absent or empty. Each service request evaluates at most 1 MB of data, or the requested Limit of items, before applying filters; an empty result page can therefore still require another request.

LastEvaluatedKey and ExclusiveStartKey

LastEvaluatedKey describes the item where DynamoDB stopped evaluating the current page. It is not necessarily the last item returned to your application, because a filter can remove that item. ExclusiveStartKey tells the next request to resume after that position.

Keep the table, index, key condition, filter and direction unchanged while following a cursor. Use the entire returned key map, including index and base-table key attributes when present. Reconstructing a cursor from only a sort key can produce an invalid starting key or skip results.

A nonempty continuation key means another request is needed to discover whether results remain. It does not guarantee that request will return a matching item. The AWS pagination documentation explicitly describes this distinction.

ValueScopeMeaning
LimitOne service requestMaximum items evaluated before filtering
CountOne service responseItems matching after filtering
ScannedCountOne service responseItems evaluated before filtering
LastEvaluatedKeyService responsePosition for the next request
ExclusiveStartKeyService requestPosition after which to resume
SDK or CLI NextTokenPaginator outputOpaque resume state for that paginator

Do not mix service keys with SDK or CLI tokens. The separate PartiQL API also has a NextToken, but it belongs to that API, not to Query or Scan.

Manual Query pagination with SDK v3

This example uses invoices with String partition key accountId and String sort key createdAt. Dates are consistently formatted UTC timestamps. Install @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb, configure credentials and a Region, and run it as an ES module.

The loop processes one page at a time, which keeps memory bounded. If a small result set is needed as an array, append each page's items to an accumulator instead. For a reconciliation job, persist output and a checkpoint only after processing succeeds, and make replaying a page safe.

Do not use Items.length || LastEvaluatedKey as the loop condition. A final nonempty page without a key would run the loop again with no starting position, restarting the query. Do not use Items.length alone either: an empty filtered page can precede more matches.

SDK v3 paginateQuery and paginateScan

The document client provides async iterators that handle service continuation keys. Both paginator functions below come from @aws-sdk/lib-dynamodb, so inputs and results use ordinary JavaScript values. The AWS SDK v3 examples use this interface.

pageSize controls the evaluated-item limit per service call. It does not guarantee that many returned items and does not limit total work. Fully consuming paginateScan still reads the table; breaking out of the iterator stops requesting later pages. The Scan guide covers pacing and parallel workers.

Python boto3 paginators

Use the low-level boto3 client to obtain a Query or Scan paginator. Unlike the JavaScript document client, this interface uses DynamoDB JSON with explicit type descriptors.

For a whole-table scan, use client.get_paginator("scan") and remove the query-only key condition and its placeholders. PaginationConfig.PageSize controls individual service requests; MaxItems limits the paginator's returned items. If you use MaxItems, resume with the paginator's token rather than a raw service key. For a deliberately small bounded result:

build_full_result() collects the selected results in memory. Prefer the page iterator for large jobs. The boto3 Query paginator reference defines these configuration fields.

AWS CLI v2 auto-pagination

The CLI automatically follows Query and Scan pages unless you disable pagination. --no-cli-pager only disables the terminal display pager; it does not disable network pagination.

If the result includes NextToken, copy it unchanged into the next invocation's --starting-token while keeping the other options the same. For example, after assigning that output token to a shell variable named TOKEN, append --starting-token "$TOKEN" to the command.

CLI optionEffect
--page-sizeSets the service request page size; the CLI still follows more pages
--max-itemsCaps items in the CLI's aggregated output and may emit NextToken
--starting-tokenResumes an earlier CLI paginator result
--no-paginateMakes just one service request
--limitSets DynamoDB's evaluated-item limit; it is not an aggregate CLI output cap
--exclusive-start-keySupplies a raw DynamoDB continuation key

For manual service pagination, combine --no-paginate with --limit, save LastEvaluatedKey as JSON, and pass that map with --exclusive-start-key file://last-key.json. Do not feed a CLI NextToken to --exclusive-start-key. When resuming CLI pagination, keeping --page-size and --max-items equal avoids the client-side truncation mismatch described in the AWS CLI pagination guide.

Filters and application page sizes

A UI asking for 20 visible invoices may need several service calls if a FilterExpression removes candidates. Decide whether to return a short page with a next cursor, or keep reading until you collect enough results. Put a maximum on requests, evaluated items or elapsed time so a sparse match cannot create an unbounded API request.

If you collect more items than the UI page can display, retain the overflow in cursor state or choose a continuation position that does not skip it. Returning the service's end-of-page key after discarding undisplayed matches loses those matches. An easier contract returns complete service pages, with a variable number of visible items.

Smaller pages smooth resource usage and let callers stop early. Reading all pages still incurs the full read work; splitting the same job into more calls is not itself a cost reduction. Choose the correct key access pattern first, as described in Query vs Scan.

Encode a cursor for an HTTP API

Keep DynamoDB's key structure behind an opaque application cursor. For a schema with String keys, base64url encoding is a convenient transport format:

This demonstrates encoding, not a complete public API security boundary. Base64 is reversible and provides no tamper protection. Reject oversized or malformed input, validate exact key fields and types, bind the cursor to the authenticated account and query parameters, and sign it or keep cursor state server-side. Always derive authorization constraints from the session, not from the cursor. If the cursor carries sensitive values, encryption or a server-side reference also prevents disclosure.

Use a serializer that preserves binary keys and high-precision numeric keys if your schema includes them. A plain JSON round trip is sufficient for the String-key example above, but is not a universal DynamoDB key codec.

Page numbers, offsets, ordering and totals

DynamoDB Query and Scan do not support an SQL-style offset. To reach page 10, you must traverse preceding pages or reuse previously saved starting cursors. Infinite scroll and next-page links fit this model. For a previous-page button, retain the starting cursor for each displayed page; the cursor is not inherently bidirectional.

Query returns sort-key order, and ScanIndexForward: false reverses it. A Scan has no useful application sort order. Neither a series of queries nor a strongly consistent scan gives a frozen snapshot across the entire traversal. Inserts and updates can change what later pages contain, so define whether a UI shows live data or needs an independently materialized snapshot.

You can obtain an exact matching count by paginating Select: "COUNT" and summing each response's Count, but this still reads the candidates. A maintained counter is an alternative for frequently displayed totals. Avoid promising a stable page count for a live, changing dataset.

For invoice updates and reconciliation, process every required page even if the initial dataset seems small. The service's byte boundary still applies when your application does not expose page navigation. Large tables are distributed internally, but the application continues through the same key-based API. DynamoDB Streams use shard iterators and GetRecords, a different protocol covered in the Streams guide.

Frequently Asked Questions

Does DynamoDB support pagination?

Yes. Query and Scan return LastEvaluatedKey when another request is needed. Pass the entire map as ExclusiveStartKey and stop when the key is absent or empty.

What is LastEvaluatedKey?

It identifies where DynamoDB stopped evaluating a page. It can refer to an item excluded by a filter and does not guarantee that another matching item exists.

Why does an empty page have a LastEvaluatedKey?

DynamoDB applies filters after the evaluated-item and byte limits. Every candidate in a page can be filtered out while later pages remain to be evaluated.

Can I jump to a page number or use offset?

There is no native offset for Query or Scan. Traverse earlier pages or store their starting cursors; next-page navigation is usually simpler.

Can I get the total count?

Yes, by paginating a COUNT request and adding each page's Count, which still consumes read capacity. For a frequently needed total, maintain a counter with consistency rules appropriate to the application.

Is an AWS CLI NextToken the same as LastEvaluatedKey?

No. Pass CLI NextToken to --starting-token. Pass a raw service LastEvaluatedKey to --exclusive-start-key; the formats are not interchangeable.

Dynobase is a Professional GUI Client for DynamoDB

Start your 7-day free trial today

Product Features

Download
/
Pricing
/
Member Portal
/
Privacy
/
EULA
/
Twitter
© 2026 Dynobase