How do you count items in DynamoDB?
Use Select: 'COUNT' on a Query or Scan to count matching items without returning them. Each response counts only up to 1 MB scanned, so you must paginate with LastEvaluatedKey and sum the Count values for a full total. For an approximate table total, read ItemCount from DescribeTable. For a grouped count — or a SUM/AVG over a column — DynoTable's SQL Workbench runs COUNT and GROUP BY as a single query and handles the pagination for you.
Counting matched items exactly
Set Select to COUNT on a Query (for one partition key) or Scan (whole table). The response returns Count and ScannedCount but no item data. If the scanned data exceeds 1 MB, the operation stops and returns LastEvaluatedKey — keep calling and adding up Count until it is absent. Note that counting is not cheaper than reading: COUNT consumes the same read capacity as returning the items would.
Count vs ScannedCount
Count— items matching your key/filter conditions in this page.ScannedCount— items examined before filtering. A filter expression narrows results but does not reduce what was scanned (or its cost).
COUNT is not a discount, measured
"Counting costs the same as reading" is easy to assert and easy to doubt, so here it is on a table holding 40 items of roughly 3 KB each (120,700 bytes in total), each call made with ReturnConsumedCapacity: 'TOTAL':
| Request | Count | ScannedCount | ConsumedCapacity |
|---|---|---|---|
Query with Select: 'COUNT' | 40 | 40 | 15 |
Query returning the items | 40 | 40 | 15 |
Scan, Select: 'COUNT', filter matching half | 20 | 40 | 15 |
The third row is the one to look at. The filter halves Count, leaves ScannedCount alone, and moves the bill by nothing.
15 is the number you would predict: 120,700 bytes rounds up to 30 four-kilobyte read units, halved because a Query is eventually consistent unless you ask otherwise.
The cheap approximation
DescribeTable returns ItemCount, a table-wide estimate updated roughly every six hours. It is free and instant, but not real-time — good for dashboards, not for exact totals.
One warning if you test against DynamoDB Local: it updates ItemCount immediately. Writing 40 items and calling DescribeTable there returns 40 straight away. The real service will not, so freshness logic that passes locally can be six hours wrong in production.
Counting and aggregating with DynoTable
The raw API gives you COUNT but no GROUP BY, SUM, or AVG — grouping and summing normally happen in your application code. DynoTable's SQL Workbench adds them: write SELECT COUNT(*), SUM(total), or a grouped count, and it runs the pagination loop for you, refining the number as pages stream in. It still reads through DynamoDB, so the same read-capacity cost applies — but you write one query instead of a loop, and you get grouped and summed results the API can't return directly.
Go deeper
Read count, sum, and aggregate in DynamoDB and build count queries with the Expression Builder. Download DynoTable to run counts and aggregates (COUNT, SUM, GROUP BY) against your tables.
References
- Query — Amazon DynamoDB API Reference
- Scan — Amazon DynamoDB API Reference
- TableDescription — Amazon DynamoDB API Reference
Last verified 2026-07-13 against the official AWS documentation linked above.
The capacity figures were reproduced 2026-07-28 against DynamoDB Local 3.3.0 (amazon/dynamodb-local:latest) via @aws-sdk/client-dynamodb 3.1095.0. DynamoDB Local is not the service; the ItemCount divergence noted above is one place they differ.