DynamoDB Scan in Go (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 Go v2 the built-in ScanPaginator follows LastEvaluatedKey until the whole table is read.

Code

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
	ctx := context.TODO()
	cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
	if err != nil {
		log.Fatalf("load config: %v", err)
	}
	client := dynamodb.NewFromConfig(cfg)

	paginator := dynamodb.NewScanPaginator(client, &dynamodb.ScanInput{
		TableName:        aws.String("Music"),
		FilterExpression: aws.String("#filter0 >= :filterValue0"),
		ExpressionAttributeNames: map[string]string{
			"#filter0": "Year",
		},
		ExpressionAttributeValues: map[string]types.AttributeValue{
			":filterValue0": &types.AttributeValueMemberN{Value: "2010"},
		},
	})

	var items []map[string]types.AttributeValue
	for paginator.HasMorePages() {
		page, err := paginator.NextPage(ctx)
		if err != nil {
			log.Fatalf("scan: %v", err)
		}
		items = append(items, page.Items...)
	}
	fmt.Printf("Matched %d items\n", len(items))
}

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 (#filter0Year), which keeps reserved words like Year safe.
  • Pagination — each Scan page reads at most 1 MB before filtering, so a filtered page can come back empty while the table still has matches. dynamodb.NewScanPaginator keeps calling until LastEvaluatedKey is exhausted — never stop at the first page.
  • Set 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 goroutines with Segment / TotalSegments (a parallel scan).
  • Prefer Query. Scan reads 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.

References

Last verified 2026-07-13 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

DynoTable is a fast desktop client for DynamoDB — browse tables, run SQL-style queries, and edit items locally.