DynamoDB S3 Export Now Supports Filter Specification. Tried It with Full and Incremental Exports

DynamoDB S3 Export Now Supports Filter Specification. Tried It with Full and Incremental Exports

Tested the newly added filter specification for DynamoDB Export to S3 with both Full and Incremental exports, checking if only needed items can be output from snapshots of frequently updated tables.
2026.10.04

This page has been translated by machine translation. View original

Introduction

On 2026-10-01, DynamoDB Export to S3 added support for Filtered export. It can be used with both Full export and Incremental export, and is available in all regions except GovCloud.

https://aws.amazon.com/blogs/database/introducing-filtered-export-from-amazon-dynamodb-to-amazon-s3/

https://aws.amazon.com/about-aws/whats-new/2026/10/amazon-dynamodb-introduces-filtered-export/

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataExport.Filtered.html

Three Expressions You Can Specify

In Filtered export, you can specify the following three expressions in --filter-specification.

Expression Syntax Rules Amount Read
KeyCondition Same as Query. PK is an equality condition with a single value, SK can be any condition Decreases
Filter Same as Scan. Applied after reading Does not decrease
Projection Specifies which attributes to output —

Export runs asynchronously, does not consume read capacity (RCU), and does not affect table performance. The pricing is the same unit price as conventional export, with no additional charge for filters. An export where the PK is narrowed down to a single value using KeyCondition is billed only for what was read, with a minimum charge of 10MB per export. The minimum charge for Incremental export is also 10MB.

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataExport.HowItWorks.html

Verification Environment

  • Region: ap-northeast-1
  • AWS CLI: aws-cli/2.37.8
  • Table: PK is TenantId, SK is WorkOrderId, on-demand, PITR enabled
  • Attributes: Status / Priority / CustomerEmail / CustomerPhone / AmountDue / UpdatedAt
  • Item count: 400 items for tenant-A, 400 for tenant-B, 200 for tenant-C, totaling 1,000 items (all fictitious data)

This is an example assuming a table that manages tenants by PK. At around 1,000 items, a filter-less export would not be problematic, but since the purpose is to confirm how each expression narrows down the output, we are testing with a small amount of data.

Filtering with Full Export

Specifying PK Value and SK Prefix Match with KeyCondition

Only items from tenant-A where WorkOrderId starts with WO-01 were output. The specification was saved to f1-filter.json and passed via --filter-specification.

{
  "KeyConditionExpression": "#tid = :tid AND begins_with(#wo, :prefix)",
  "ExpressionAttributeNames": {"#tid": "TenantId", "#wo": "WorkOrderId"},
  "ExpressionAttributeValues": {":tid": {"S": "tenant-A"}, ":prefix": {"S": "WO-01"}}
}
aws dynamodb export-table-to-point-in-time --table-arn <テーブルARN> --export-time 2026-10-03T09:54:00Z --s3-bucket <バケット名> --s3-prefix f1/ --export-format DYNAMODB_JSON --filter-specification file://f1-filter.json

The output was 100 items, all from tenant-A with WO-0100 through WO-0199. A Query with the same condition (--select COUNT) also returned 100 items. The first line is as follows.

{"Item":{"WorkOrderId":{"S":"WO-0100"},"TenantId":{"S":"tenant-A"},"CustomerPhone":{"S":"+81-90-0000-0100"},"UpdatedAt":{"S":"2026-10-03T09:00:00Z"},"Priority":{"S":"NORMAL"},"AmountDue":{"N":"1100"},"Status":{"S":"IN_PROGRESS"},"CustomerEmail":{"S":"user0100@example.com"}}}

Each line of the Full export was in DynamoDB JSON format with Item as the key. The applied filter specification is not included in the response immediately after requesting the export. It can be confirmed in the FilterSpecification of DescribeExport.

Filtering Items and Attributes with Filter and Projection

Items were narrowed down to those with Status COMPLETED, and the output attributes were limited to four. Since Status is a reserved word, an alias (#st) is used in the expression. The specification was saved to f2-filter.json and executed.

{
  "FilterExpression": "#st = :done",
  "ProjectionExpression": "#tid, #wo, #st, #amt",
  "ExpressionAttributeNames": {"#tid": "TenantId", "#wo": "WorkOrderId", "#st": "Status", "#amt": "AmountDue"},
  "ExpressionAttributeValues": {":done": {"S": "COMPLETED"}}
}
aws dynamodb export-table-to-point-in-time --table-arn <テーブルARN> --export-time 2026-10-03T09:54:00Z --s3-bucket <バケット名> --s3-prefix f2/ --export-format DYNAMODB_JSON --filter-specification file://f2-filter.json

The output was 333 items, broken down as 133 for tenant-A, 133 for tenant-B, and 67 for tenant-C. The first line is as follows.

{"Item":{"AmountDue":{"N":"1002"},"Status":{"S":"COMPLETED"},"TenantId":{"S":"tenant-A"},"WorkOrderId":{"S":"WO-0002"}}}

All lines had Status=COMPLETED, and unspecified attributes including CustomerEmail and CustomerPhone were not output. Output excluding contact information can be created simply by listing the attributes to retain in the Projection.

Filtering with Incremental Export

Changes Within the Target Period and KeyCondition

The target period was set to 15 minutes from ExportFromTime to ExportToTime. The insertion of 1,000 items was completed before the start of the target period, and the following changes were made after the start.

Change TenantId WorkOrderId Before → After
Update tenant-A WO-0003 OPEN → COMPLETED, AmountDue 1003 → 999001
Update tenant-A WO-0002 COMPLETED → OPEN, AmountDue 1002 → 999002
Update tenant-A WO-0008 Remained COMPLETED, AmountDue 1008 → 999003
Update tenant-B WO-0003 OPEN → COMPLETED, AmountDue 1003 → 999004
Delete tenant-A WO-0005 Was COMPLETED before deletion
Delete tenant-A WO-0004 Was IN_PROGRESS before deletion
Add tenant-A WO-0401 COMPLETED, AmountDue 500
Add then delete tenant-A WO-0402 Deleted within target period after addition

The target period was specified in incremental-spec.json.

{"ExportFromTime": "2026-10-03T09:54:30Z", "ExportToTime": "2026-10-03T10:09:30Z", "ExportViewType": "NEW_AND_OLD_IMAGES"}

The KeyCondition to narrow down to only tenant-A was saved as i1-filter.json. This export is referred to below as I1.

{
  "KeyConditionExpression": "#tid = :tid",
  "ExpressionAttributeNames": {"#tid": "TenantId"},
  "ExpressionAttributeValues": {":tid": {"S": "tenant-A"}}
}
aws dynamodb export-table-to-point-in-time --table-arn <テーブルARN> --export-type INCREMENTAL_EXPORT --incremental-export-specification file://incremental-spec.json --s3-bucket <バケット名> --s3-prefix i1/ --export-format DYNAMODB_JSON --filter-specification file://i1-filter.json

The output was 6 items, all from tenant-A. Each line had a structure containing Keys / Metadata / NewImage / OldImage, which differs in shape from the Item in Full export. Since no Projection was specified, each image had 8 attributes.

The 3 updated items (WO-0002, WO-0003, WO-0008) output both OldImage and NewImage. The 2 deleted items (WO-0004, WO-0005) output only OldImage, and the 1 added item (WO-0401) output only NewImage. tenant-B's WO-0003 was not included because its PK value differed from the KeyCondition. WO-0402, which was added and then deleted within the target period, was also not included in the output.

Filter is Evaluated Against the Latest Image

Without a KeyCondition, Filter and Projection were specified for the same target period. The specification was the same as f2-filter.json (Filter for Status COMPLETED and Projection of 4 attributes), saved as i2-filter.json. This export is referred to below as I2. The command executed was the same as the command in the previous subsection with the values of --s3-prefix and --filter-specification replaced with i2/ and file://i2-filter.json respectively.

The output was 5 items. For the 7 changes within the target period excluding WO-0402 (which was added then deleted), the outputs of I1 (KeyCondition only) and I2 (Filter and Projection) are mapped below.

TenantId / WorkOrderId Change Latest Image I1 (KeyCondition only) I2 (Filter: Status=COMPLETED)
tenant-A / WO-0003 OPEN → COMPLETED COMPLETED Included Included
tenant-A / WO-0008 Remained COMPLETED, amount changed COMPLETED Included Included
tenant-A / WO-0401 Added (COMPLETED) COMPLETED Included Included
tenant-A / WO-0005 Deleted (was COMPLETED before deletion) None (evaluated by old image) Included Included
tenant-B / WO-0003 OPEN → COMPLETED COMPLETED Not included Included
tenant-A / WO-0002 COMPLETED → OPEN OPEN Included Not included
tenant-A / WO-0004 Deleted (was IN_PROGRESS before deletion) None (evaluated by old image) Included Not included

The Filter in Incremental export is evaluated against the latest image of each item. Deleted items are evaluated by their old image.

Looking at the first line of I2 (WO-0003 of tenant-A), the Projection was applied to both OldImage and NewImage.

{"Metadata":{"WriteTimestampMicros":{"N":"1791021301924409"}},"Keys":{"TenantId":{"S":"tenant-A"},"WorkOrderId":{"S":"WO-0003"}},"OldImage":{"AmountDue":{"N":"1003"},"Status":{"S":"OPEN"},"TenantId":{"S":"tenant-A"},"WorkOrderId":{"S":"WO-0003"}},"NewImage":{"AmountDue":{"N":"999001"},"Status":{"S":"COMPLETED"},"TenantId":{"S":"tenant-A"},"WorkOrderId":{"S":"WO-0003"}}}

Errors When Specification is Invalid

After trying the following four types of specifications, a ValidationException was returned before the export started in all cases.

Specification Message
Empty specification ({}) Invalid FilterSpecification: The specification can not be empty
TenantId in both KeyCondition and Filter Invalid FilterExpression: key attributes are not allowed in the filter expression when a KeyConditionExpression is present: TenantId
Using non-equality operator for PK in KeyCondition (#tid > :tid) Invalid KeyConditionExpression: only the equality operator is supported for the partition key: TenantId
Writing the reserved word Status in Filter without aliasing (Status = :done) Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: Status

Summary

We confirmed that the filter specification (--filter-specification) added to DynamoDB Export to S3 works with both Full export and Incremental export.

For use cases where data from a frequently updated table is saved as a snapshot once a day at that point in time, you can use Full export with conditions to write only the necessary items and attributes to S3.

Please make use of this feature when you want to save only items meeting specific conditions from DynamoDB to S3, or when you want to pre-classify data by S3 prefix.

Share this article

AWSのお困り事はクラスメソッドへ