DynamoDB reads either a specific set of items with Query or the whole table with Scan. A Query uses the primary key or an index and reads only matching items; a Scan reads everything and filters afterward, so its cost grows with table size.
Before you start
You should understand partition and sort keys. This article covers Query, Scan and indexes.
Step-by-step walkthrough
Step 1: Query by key, not by filter
A Query requires an equality condition on the partition key, with optional conditions on the sort key, so it reads a bounded set. Design the key so the common access pattern is a query, such as PK = user#42, SK begins_with order#. The key is the query.
Step 2: Understand why Scan is expensive
A Scan reads every item and applies the filter after reading, so it consumes read capacity proportional to the table, not the result. A FilterExpression reduces what is returned but not what is read, which surprises people who expect it to reduce cost.
Step 3: Add a secondary index for other access patterns
A global secondary index projects the attributes you need and gives an alternate partition and sort key, so a second access pattern is also a query. Each access pattern should map to a key; if it does not, the model needs another index or a different key.
Worked scenario
The query reads one user’s recent orders by key.
table: PK = user#42, SK = order#2026-01-01
Query:
KeyConditionExpression: 'PK = :pk AND begins_with(SK, :prefix)'
ExpressionAttributeValues: { ':pk': 'user#42', ':prefix': 'order#' }Walk through the example
The partition key narrows the read to user 42, and the sort-key condition selects their orders, so only those items are read. A Scan with the same filter would read the entire table and discard most of it, costing far more. The key design makes the common access pattern cheap.
Common mistake
Running a Scan on a production table because the access pattern was not modeled, which is slow and expensive, or expecting a FilterExpression to reduce consumed capacity, which it does not.
Verify the behavior
Compare consumed read capacity for a Query and a Scan returning the same items. Confirm a Query requires the partition key. Add a GSI and confirm the new access pattern becomes a Query.
Interview exercise
Why does a FilterExpression on a Scan not reduce cost?
Answer and reasoning
Because DynamoDB reads items first and applies the filter after, so capacity is consumed for every item examined regardless of the result. The filter only reduces the data returned. To reduce cost you must read fewer items, which means a key-based Query or an index.
Continue learning
Compare access patterns in DynamoDB access patterns and conditions in DynamoDB conditional writes. Read the AWS DynamoDB Query documentation and try the AWS interview questions.