Development with AWS Services · Topic 6 of 7
DynamoDB Design and Data Lifecycles
Choose DynamoDB keys and indexes, use Query versus Scan and consistency models, and expire data with TTL, S3 Lifecycle rules and retention periods.
- 5 min
- Pick a partition key with many distinct values and even access.
- Query uses the key and is efficient; Scan reads everything, and filters apply after the read.
- Reads are eventually consistent by default;
ConsistentRead=Truecosts double and fails on a GSI.
What it is
Amazon DynamoDB stores items in tables and finds them by primary key. Fast, cheap access comes from choosing keys and indexes that match the questions your code asks.
Data also has a lifecycle. Old sessions, logs and messages should expire or move to cheaper storage on their own, instead of by hand. DynamoDB uses TTL, S3 uses Lifecycle rules, and other services use retention periods.
How it works
Keys and attributes
The primary key is either a partition key alone or a partition key plus a sort key. DynamoDB hashes the partition key to pick the physical partition, and keeps items with the same partition key sorted by the sort key.
- Choose a high cardinality partition key, meaning one with many distinct values and evenly spread traffic, such as
customerId. A key likestatussends most traffic to one partition and causes throttling on a hot partition. - Other attributes are schema free, and one item can be up to 400 KB.
- A composite key such as
customerIdplusorderDatelets one Query return a customer's orders in order.
Query, Scan and writes
| Operation | What it does | Cost |
|---|---|---|
GetItem | Reads one item by full key | Cheapest |
Query | Needs the partition key, optionally a sort key condition | Reads only that collection |
Scan | Reads every item in the table or index | Reads and pays for everything |
A filter expression on a Scan or Query runs after the read, so it shrinks the response but not the capacity used. Each call returns at most 1 MB, and LastEvaluatedKey is your cue to call again with ExclusiveStartKey.
resp = table.query(
KeyConditionExpression=Key("customerId").eq("c-17")
& Key("orderDate").begins_with("2026-10"),
ProjectionExpression="orderId, total",
)
For writes, PutItem replaces an item and UpdateItem changes attributes, including atomic counters. A ConditionExpression makes a write conditional, which supports optimistic locking with a version attribute. BatchGetItem, BatchWriteItem and transactions group operations.
Read consistency and capacity
| Eventually consistent | Strongly consistent | |
|---|---|---|
| Default | Yes | Set ConsistentRead=True |
| Freshness | May lag a recent write | Latest committed data |
| Cost | One RCU reads two items of 4 KB | One RCU reads one item of 4 KB |
| On a GSI | Supported | Not supported |
One write capacity unit writes one item of up to 1 KB per second. In provisioned mode you set capacity, and in on demand mode DynamoDB scales for you. An exceeded limit returns ProvisionedThroughputExceededException, which the SDK retries with backoff.
Indexes
| Local secondary index | Global secondary index | |
|---|---|---|
| Keys | Same partition key, different sort key | Any partition key and sort key |
| Created | Only at table creation | Any time |
| Consistency | Eventual or strong | Eventual only |
| Capacity | Shares the table's | Has its own |
Query an index by passing IndexName. Each index copies the attributes you project into it.
Expiring data with TTL
Enable TTL on a table and name an attribute that holds a Number of Unix epoch seconds. DynamoDB deletes expired items in the background, typically within a few days, and the deletes use no write capacity.
Expired items can still be returned until they are deleted, so filter them out in queries. TTL deletions appear in DynamoDB Streams.
S3 Lifecycle and retention periods
An S3 Lifecycle configuration is a set of rules, each with a filter by prefix, tag or size.
- Transition actions move objects between storage classes, for example Standard to Glacier Flexible Retrieval after 30 days. Objects smaller than 128 KB do not transition by default.
- Expiration actions delete current objects, noncurrent versions or expired delete markers, and can abort incomplete multipart uploads.
{"Rules":[{"ID":"logs","Status":"Enabled","Filter":{"Prefix":"logs/"},
"Transitions":[{"Days":30,"StorageClass":"GLACIER"}],
"Expiration":{"Days":365}}]}
Other services use retention periods. SQS keeps messages for 4 days by default, up to 14. Kinesis keeps records for 24 hours by default, up to 365 days. CloudWatch Logs keeps events forever unless you set a retention period on the log group.
How the exam asks about this
- "Session items must disappear after 24 hours without any cleanup code." -> Enable TTL and store an expiry epoch in a Number attribute.
- "Queries by email are needed on a table keyed by userId." -> Add a global secondary index on email.
- "Logs in S3 are rarely read after 30 days and must be deleted after a year." -> A Lifecycle rule with a transition and an expiration.
What to remember for the exam
- Pick a partition key with many distinct values and even access.
- Query uses the key and is efficient; Scan reads everything, and filters apply after the read.
- Reads are eventually consistent by default;
ConsistentRead=Truecosts double and fails on a GSI. - A GSI can be added later, has its own capacity and is eventually consistent; an LSI exists only from table creation.
- TTL needs a Number attribute in epoch seconds, deletes lazily and consumes no write capacity.
- S3 Lifecycle rules transition and expire objects by prefix, tag or size.
- Retention is set per service: SQS up to 14 days, Kinesis up to 365 days, log groups by policy.
TTL is not exact. Do not rely on it for security or compliance deadlines, because expired items can remain readable for days.
Common mistakes
Using Scan for a routine lookup. A Scan with a filter still reads the whole table. Add a key or an index instead.
Storing the TTL as a string or in milliseconds. The attribute must be a Number in seconds, or the item is ignored.
Expecting strong reads from a GSI. Indexes replicate asynchronously. Use the base table for strongly consistent reads.
Check yourself
Why is
statusa poor partition key?It has few distinct values, so traffic concentrates on a few partitions and causes hot partition throttling.
When can you create a local secondary index?
Only when the table is created; a global secondary index can be added later.
What type and unit must a TTL attribute use?
A Number holding Unix epoch time in seconds.
Topic 6 of 7 in Development with AWS Services
Test yourself on Development with AWS Services
The full AWS DVA-C03 question bank has 850 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by AWS. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.