skip to content

What is a DynamoDB Stream, what does the StreamViewType setting control, and what ordering and retention guarantees does the stream give a consumer?

level: middleimportance: should knowfreq 56%

answer

  1. a change log, not a queue
  2. four levels of detail per record
  3. the clock runs out in a day
  4. ordered within a key only
  5. assume you will see it twice

basics

~20 s

A DynamoDB Stream is an ordered, 24-hour log of every item-level change in a table. StreamViewType chooses whether each record carries keys only, the new image, the old image, or both. Ordering is guaranteed per item, not table-wide.

solid answer

~40 s

Enabling a stream on a table makes DynamoDB emit one record for every insert, update and delete, in a time-ordered log that is retained for 24 hours. `StreamViewType` decides how much of the item each record carries: `KEYS_ONLY`, `NEW_IMAGE`, `OLD_IMAGE`, or `NEW_AND_OLD_IMAGES` — the last is what change-data-capture and replication generally need, since a consumer usually wants the before and after. The ordering guarantee is the part candidates get wrong: records for the *same* partition key appear in the order the changes were applied, but there is no global ordering across keys, because the stream is sharded roughly along the table's partitions. Each change appears exactly once in the stream, though delivery to a consumer is at-least-once, so handlers must be idempotent. Typical consumers are Lambda, Kinesis Client Library applications, and global tables replication.

code

bash · 6 lines
bash
aws dynamodb update-table \
  --table-name Orders \
  --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

aws dynamodb describe-table --table-name Orders \
  --query 'Table.LatestStreamArn'

go deeper

for a junior

Know that enabling a stream makes DynamoDB emit a record for every item change, that StreamViewType decides whether the record includes the old value, the new value, both, or just the keys.

for a middle

Be ready to state the 24-hour retention, explain that ordering is guaranteed per partition key because the stream is sharded, and say why consumers must be idempotent.

for a senior

Show that you treat retention as a failure-mode constraint: alarm on consumer lag, keep a table-scan or restore-based rebuild path, and choose the view type against a concrete downstream contract.

for a principal

Own the choice between native Streams and streaming to Kinesis across the estate, and the standard every team follows for idempotency, lag alerting and downstream state rebuilds.

## What the stream is A DynamoDB Stream is a change log attached to a table. Once enabled, every item-level modification — a `PutItem` that creates an item, an `UpdateItem` that changes one attribute, a `DeleteItem`, an expiry performed by the table's Time to Live setting — produces one **stream record**. The stream is a separate API surface (`streams.dynamodb.<region>.amazonaws.com`) with its own operations such as `DescribeStream`, `GetShardIterator` and `GetRecords`, deliberately shaped like the Kinesis Data Streams API so the same client libraries can consume it. Enabling a stream is a table setting: ```bash aws dynamodb update-table \ --table-name Orders \ --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES ``` Streams are not billed by capacity units; you pay per read request against the stream, and writes to the table do not consume extra write capacity to populate it. ## StreamViewType: how much of the item travels Four values, chosen once per stream: - `KEYS_ONLY` — only the key attributes of the changed item. Smallest records; a consumer that needs the current value must read the table, which also means it sees the *latest* value rather than the value at the time of the change. - `NEW_IMAGE` — the entire item as it looks after the change. Good for projecting into a search index or a cache. - `OLD_IMAGE` — the entire item as it looked before. Good for audit trails of what was removed, and the only way to see the contents of a deleted item. - `NEW_AND_OLD_IMAGES` — both. The default choice for change-data-capture, replication and anything that must compute a diff, and what global tables uses internally. Changing the view type requires disabling and re-enabling the stream, which creates a new stream with a new ARN and loses whatever was in the old one, so it is worth getting right at design time. Each record also carries an `eventName` of `INSERT`, `MODIFY` or `REMOVE`, and for TTL expiries a `userIdentity` block identifying the principal as the DynamoDB service — the standard way to distinguish an expiry from a real user delete. ## Ordering: per item, not per table The stream is divided into **shards**, which correspond roughly to the table's partitions, and each shard is an ordered sequence. All changes to a given partition key land in the same shard lineage, so a consumer sees that item's history in the order the changes happened. Across different keys there is no ordering guarantee at all: an update to item A that happened before an update to item B may be read after it, because they are in different shards being consumed in parallel. This is the right guarantee for most use cases — you almost always care that one order's status transitions arrive in sequence, not that two unrelated orders are interleaved correctly — but it quietly breaks any design that assumes a global timeline, such as reconstructing a table-wide audit log by naive concatenation. Shards are also not permanent: they split and close as partitions split, and a consumer must follow the parent-child shard lineage. That bookkeeping is exactly what the Kinesis Client Library, or Lambda's managed poller, does for you. ## Retention and delivery semantics Stream data is retained for **24 hours**, after which it is deleted regardless of whether anyone read it. That single number drives a lot of operational design: a consumer that is broken over a weekend does not just lag, it loses data permanently. Monitoring consumer lag is therefore not optional, and a rebuild path that does not depend on the stream — re-scanning the table, or restoring from a backup — is a required part of any stream-based pipeline. Each change appears in the stream **exactly once**. Delivery to a consumer is **at least once**: retries, shard-iterator restarts and consumer restarts all cause records to be re-read. Consumers must be idempotent — key the downstream effect on something stable such as the item's key plus a version attribute, or the record's sequence number. ## Choosing the stream, or Kinesis instead DynamoDB also offers streaming a table's changes to a Kinesis Data Stream instead. That option trades guarantees for reach: it gives you longer, configurable retention and the whole Kinesis consumer ecosystem, but records may arrive out of order relative to the item's history and duplicates are possible, so it suits analytics fan-out more than replication. Native DynamoDB Streams are the choice when per-item ordering matters. ## What interviewers listen for Name the four view types and pick one for a stated purpose; state the 24-hour retention as a design constraint rather than a fact; and be precise about ordering — per partition key, not global. Adding that delivery is at-least-once and therefore handlers must be idempotent is usually the sentence that separates a real practitioner from someone who has read the feature page.

  • A consumer of a DynamoDB Stream was broken for two days. What is the recovery path?
    Everything older than 24 hours is gone — the stream cannot be replayed further back. Recovery means rebuilding downstream state from the table itself: a full scan, an export to S3, or a point-in-time restore into a side table that you then read. Design that rebuild path up front, and alarm on consumer lag so the gap is caught in minutes rather than days.
  • How does a stream consumer tell an item removed by TTL apart from one deleted by a user?
    The stream record for a TTL expiry carries a userIdentity block whose principal identifies the DynamoDB service itself, while a user delete does not. Both arrive as eventName REMOVE with the old image if the view type includes it, so the userIdentity field is the reliable discriminator — useful when expiry should archive the item but a real delete should propagate as a delete.
  • Why can't you simply change a table's StreamViewType from NEW_IMAGE to NEW_AND_OLD_IMAGES?
    The view type is fixed for the life of a stream. Changing it means disabling the stream and enabling a new one, which produces a new stream ARN and drops any records the old stream still held. Consumers must be repointed at the new ARN, and there is a gap unless you overlap them, so pick the widest view you might need at design time.

saying these in an interview costs you the question

  • Stream records are ordered globally across the whole table
  • Streams retain data until a consumer acknowledges it
  • Each record is delivered to a consumer exactly once
  • A deleted item's contents are always visible in the record
  • StreamViewType can be changed on a live stream in place

context