DynamoDB Scan in Java (AWS SDK v2)
Scan reads every item in a table or index, page by page, then optionally drops rows with a FilterExpression. In AWS SDK for Java 2.x you build a ScanRequest and let the built-in scanPaginator follow LastEvaluatedKey until the whole table is read.
Code
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
public class ScanExample {
public static void main(String[] args) {
try (DynamoDbClient ddb = DynamoDbClient.builder()
.region(Region.US_EAST_1)
.build()) {
Map<String, String> names = new HashMap<>();
names.put("#filter0", "Year");
Map<String, AttributeValue> values = new HashMap<>();
values.put(":filterValue0", AttributeValue.builder().n("2010").build());
ScanRequest request = ScanRequest.builder()
.tableName("Music")
.filterExpression("#filter0 >= :filterValue0")
.expressionAttributeNames(names)
.expressionAttributeValues(values)
.build();
List<Map<String, AttributeValue>> items = new ArrayList<>();
for (ScanResponse page : ddb.scanPaginator(request)) {
items.addAll(page.items());
}
System.out.println("Matched " + items.size() + " items");
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
}
}
}Explanation
filterExpression— applied after the read, on the server. It shrinks the response but not the cost: you pay to read every item scanned, filtered or not.expressionAttributeNames— the filtered attribute is aliased (#filter0→Year), which keeps reserved words likeYearsafe.- Pagination — each
Scanpage reads at most 1 MB before filtering, so a filtered page can come back empty while the table still has matches.ddb.scanPaginator(request)returns aScanIterablethat keeps requesting pages untilLastEvaluatedKeyis exhausted — never stop at the first page. - Add
.limit(...)to cap items scanned per page (pre-filter) — it does not cap items returned. - For a large full-table scan, split the work across workers with
.segment(...)/.totalSegments(...)(a parallel scan). - Prefer
Query.Scanreads the whole table; on anything but a tiny table it's slow and expensive.
Do it visually
Assembling a filter by hand? The DynamoDB Expression Builder builds the FilterExpression + name/value maps and copies runnable code.
To explore tables in a GUI — with filtered, paginated result grids and copy-as-code — download DynoTable, instead of scanning blind from a script.
Related examples
- DynamoDB Scan in Go — the same scan with AWS SDK for Go v2.
- DynamoDB Query in Java — the cheaper read you should usually reach for.
- Query vs. Scan — when (rarely) a
Scanis justified. - Why is my DynamoDB Scan slow and expensive? — the cost model and how to avoid it.
- DynamoDB ProvisionedThroughputExceededException — what a full-table scan does to a provisioned table's capacity.
- DynamoDB ThrottlingException — the other throttle, and how exponential backoff handles it.
References
- Scan — Amazon DynamoDB API Reference
- Use Scan with an AWS SDK or CLI — Amazon DynamoDB Developer Guide
- DynamoDbClient — AWS SDK for Java 2.x API Reference
- ScanRequest — AWS SDK for Java 2.x API Reference
- Scanning tables — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.