Skip to content
Back to main site

Amazon DynamoDB Streams

Read INSERT, MODIFY and REMOVE records from an emulated DynamoDB table.

Plan: Free4 of 4 operations implemented

A single local shard was tested; retention, iterator expiry, resharding and Lambda event-source delivery were not verified.

Example checked on Vera 1.2.2, 8 November 2026. Each coverage note names its own evidence and date.

This Free service needs no license key. Start Vera as in Get started, then run this in a terminal of its own, from an empty scratch directory. It gives the official AWS CLI dummy credentials and a config file of its own, so no AWS account is needed and your own AWS profile isn't touched.

Terminal window
export VERA_ENDPOINT="http://localhost:5003"
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test
export AWS_REGION=us-east-1 AWS_DEFAULT_REGION=us-east-1
export AWS_SHARED_CREDENTIALS_FILE=/dev/null
export AWS_EC2_METADATA_DISABLED=true
export AWS_PAGER="" AWS_CLI_AUTO_PROMPT=off
unset AWS_PROFILE AWS_DEFAULT_PROFILE
unset AWS_SESSION_TOKEN AWS_SECURITY_TOKEN
unset AWS_WEB_IDENTITY_TOKEN_FILE AWS_ROLE_ARN AWS_ROLE_SESSION_NAME
unset AWS_CONTAINER_CREDENTIALS_FULL_URI
unset AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
cat > vera-aws-config <<'EOF'
[default]
region = us-east-1
output = json
cli_binary_format = base64
s3 =
addressing_style = path
EOF
export AWS_CONFIG_FILE="$PWD/vera-aws-config"

When you've finished every example in this terminal, close it and delete vera-aws-config, not before.

The AWS CLI uses dynamodbstreams for reading change records and dynamodb for creating the source table and changing its items. Both go to the same VERA_ENDPOINT, and no real AWS account is needed. The emulator serves the 2012-08-10 API over the AWS JSON protocol, and the example was checked with the official AWS CLI 2.31.35 (installing it). For the table and item operations themselves, see DynamoDB.

Create a table with a NEW_AND_OLD_IMAGES stream, put, update and delete an item, then read the three change records from the stream’s first shard. The stream ARN, shard ID and shard iterator come from the responses, so the commands keep them in shell variables.

Create the table, keeping its stream’s ARN, then list its streams and keep the first shard’s ID:

Terminal window
STREAM_ARN=$(aws --endpoint-url "$VERA_ENDPOINT" dynamodb create-table \
--table-name vera-docs-stream \
--attribute-definitions AttributeName=pk,AttributeType=S \
--key-schema AttributeName=pk,KeyType=HASH --billing-mode PAY_PER_REQUEST \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
--query TableDescription.LatestStreamArn --output text)
aws --endpoint-url "$VERA_ENDPOINT" dynamodbstreams list-streams --table-name vera-docs-stream
SHARD_ID=$(aws --endpoint-url "$VERA_ENDPOINT" dynamodbstreams describe-stream \
--stream-arn "$STREAM_ARN" \
--query 'StreamDescription.Shards[0].ShardId' --output text)

list-streams lists the table’s stream, with its ARN and label, which differ on every run. Now put an item, update it and delete it:

Terminal window
aws --endpoint-url "$VERA_ENDPOINT" dynamodb put-item --table-name vera-docs-stream \
--item '{"pk":{"S":"one"},"value":{"S":"first"}}'
aws --endpoint-url "$VERA_ENDPOINT" dynamodb update-item --table-name vera-docs-stream \
--key '{"pk":{"S":"one"}}' --update-expression 'SET #v = :v' \
--expression-attribute-names '{"#v":"value"}' \
--expression-attribute-values '{":v":{"S":"second"}}'
aws --endpoint-url "$VERA_ENDPOINT" dynamodb delete-item --table-name vera-docs-stream \
--key '{"pk":{"S":"one"}}'

Get an iterator at the start of the shard, then read its records. The --query picks each record’s event name, key, and value before and after the change:

Terminal window
ITERATOR=$(aws --endpoint-url "$VERA_ENDPOINT" dynamodbstreams get-shard-iterator \
--stream-arn "$STREAM_ARN" --shard-id "$SHARD_ID" \
--shard-iterator-type TRIM_HORIZON --query ShardIterator --output text)
aws --endpoint-url "$VERA_ENDPOINT" dynamodbstreams get-records --shard-iterator "$ITERATOR" \
--query 'Records[].{Event:eventName,Key:dynamodb.Keys.pk.S,Before:dynamodb.OldImage.value.S,After:dynamodb.NewImage.value.S}'

The three records come back in order, one for each change. They’re shown here one to a line:

Output
[
{ "Event": "INSERT", "Key": "one", "Before": null, "After": "first" },
{ "Event": "MODIFY", "Key": "one", "Before": "first", "After": "second" },
{ "Event": "REMOVE", "Key": "one", "Before": "second", "After": null }
]

To clean up, delete the table:

Terminal window
aws --endpoint-url "$VERA_ENDPOINT" dynamodb delete-table --table-name vera-docs-stream

The stream can stay in list-streams after its table is deleted, and the API has no operation to delete a stream. For a clean slate, start a fresh emulator: see Stop and start again.

  • Listing streams: ListStreams lists a table’s enabled stream.
  • Describing a stream: DescribeStream returns its ENABLED status, its NEW_AND_OLD_IMAGES view type, the table’s key schema and a shard.
  • Shard iterators: GetShardIterator with TRIM_HORIZON returns an iterator that GetRecords accepts.
  • Change records: GetRecords returns INSERT, MODIFY and REMOVE records in order, and a NextShardIterator. Each record carries the item’s key and its old and new images as DynamoDB typed attribute maps, with the item’s actual values.

The main limits are below. A few more apply to every service, and the API coverage notes cover smaller differences.

  • One table and one shard were tested. Other stream view types and iterator types, sequence-number boundaries, retention windows, iterator expiry, paging limits, resharding and large items weren’t exercised. Nothing here shows that timing or scaling match AWS’s.
  • Lambda delivery wasn’t tested. Whether a Lambda event source mapping receives a stream’s records wasn’t verified.
  • Streams can outlive their tables. After its table was deleted, the stream stayed in ListStreams. Deleting the table is the only cleanup the API offers: there’s no DeleteStream operation, and retained stream metadata may not disappear at once.

Every operation in AWS's published 2012-08-10 API (SDK model, botocore 1.43.105), and whether Vera 1.2.0 preview implements it. Availability combines the earlier implementation inventory with the dated observations below; checking a page's example does not verify every operation. Each note names its evidence first; an observation given without a build or date comes from earlier testing, on 3 November 2026. What the statuses mean

OperationStatusNotes
DescribeStreamImplementedLocal observation: Vera 1.2.0 preview, 5 November 2026 — described an enabled NEW_AND_OLD_IMAGES stream with one shard in Vera 1.2.0 preview. Other stream views and shard lifecycle were not checked.
GetRecordsImplementedLocal observation: Vera 1.2.0 preview, 5 November 2026 — returned INSERT, MODIFY and REMOVE records with the expected old/new images and a NextShardIterator. Retention, paging limits and iterator expiry were not checked.
GetShardIteratorImplementedLocal observation: Vera 1.2.0 preview, 5 November 2026 — TRIM_HORIZON returned a usable iterator. Other iterator modes were not checked.
ListStreamsImplementedLocal observation: Vera 1.2.0 preview, 5 November 2026 — listed the table's stream; its stream metadata remained listed after deleting the table.