Building DynamoDB TTL: Auto-Expire Old Data
Learn how to automatically delete stale data in DynamoDB using Time-to-Live (TTL).
In this lab, you’ll add an expiration attribute to items, enable TTL on the table, and watch DynamoDB clean up expired records automatically — all from your terminal.
Step 1: Create a Table with a TTL Attribute
In this step, you’ll create a table named SessionData with a partition key (SessionID).
You’ll also include a placeholder attribute ExpiresAt, which will later store an epoch timestamp.
aws dynamodb create-table \
--table-name SessionData \
--attribute-definitions AttributeName=SessionID,AttributeType=S \
--key-schema AttributeName=SessionID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Output:
{
"TableDescription": {
"TableName": "SessionData",
"TableStatus": "CREATING",
"BillingModeSummary": { "BillingMode": "PAY_PER_REQUEST" },
"ItemCount": 0
}
}
Check table status until it’s active:
aws dynamodb describe-table --table-name SessionData --query "Table.TableStatus"
Output:
"ACTIVE"
Step 2: Insert Items with Expiration Timestamps
You’ll insert a few records with an ExpiresAt attribute that tells DynamoDB when to remove them.
TTL expects Unix epoch time (in seconds), not milliseconds.
Generate a timestamp that expires in ~5 minutes:
date -d "+5 minutes" +%s
Example Output:
1731465900
(Note: This date command works on Linux/macOS. For Windows PowerShell, use: [int][DateTimeOffset]::Now.AddMinutes(5).ToUnixTimeSeconds())
Insert two sessions:
aws dynamodb put-item \
--table-name SessionData \
--item '{"SessionID": {"S": "sess-1001"}, "User": {"S": "Alice"}, "ExpiresAt": {"N": "1731465900"}}'
aws dynamodb put-item \
--table-name SessionData \
--item '{"SessionID": {"S": "sess-1002"}, "User": {"S": "Bob"}, "ExpiresAt": {"N": "1731466200"}}'
Output:
{}
Confirm both are inserted:
aws dynamodb scan --table-name SessionData --projection-expression "SessionID, ExpiresAt"
Output:
{
"Items": [
{"SessionID": {"S": "sess-1001"}, "ExpiresAt": {"N": "1731465900"}},
{"SessionID": {"S": "sess-1002"}, "ExpiresAt": {"N": "1731466200"}}
],
"Count": 2
}
Step 3: Enable TTL on the Table
Enable DynamoDB TTL, specifying the ExpiresAt attribute:
aws dynamodb update-time-to-live \
--table-name SessionData \
--time-to-live-specification "Enabled=true, AttributeName=ExpiresAt"
Output:
{
"TimeToLiveSpecification": {
"AttributeName": "ExpiresAt",
"Enabled": true
}
}
Check TTL status:
aws dynamodb describe-time-to-live --table-name SessionData
Output:
{
"TimeToLiveDescription": {
"TimeToLiveStatus": "ENABLED",
"AttributeName": "ExpiresAt"
}
}
Step 4: Observe Item Expiration
DynamoDB’s TTL sweeper runs periodically (usually within minutes for small tables).
While waiting for it to remove expired items, you can continue querying the table to watch entries disappear in real time.
aws dynamodb scan --table-name SessionData --projection-expression "SessionID, ExpiresAt"
Example Output (after a few minutes):
{
"Items": [
{"SessionID": {"S": "sess-1002"}, "ExpiresAt": {"N": "1731466200"}}
],
"Count": 1
}
Eventually, the table will be empty as all timestamps pass.
You’ll see expired records vanish automatically — no deletes required.
Step 5: Verify Cleanup via CloudWatch Metrics
While TTL cleanup is in progress, you can use CloudWatch metrics to confirm deletion activity.
aws cloudwatch get-metric-statistics \
--namespace AWS/DynamoDB \
--metric-name TimeToLiveDeletedItemCount \
--start-time $(date -u -d "-15 minutes" +"%Y-%m-%dT%H:%M:%SZ") \
--end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--period 300 \
--statistics Sum \
--dimensions Name=TableName,Value=SessionData
Output (example):
{
"Datapoints": [
{
"Timestamp": "2025-10-20T21:45:00Z",
"Sum": 2.0,
"Unit": "Count"
}
],
"Label": "TimeToLiveDeletedItemCount"
}
This confirms DynamoDB’s background sweeper removed the expired items.
Step 6: Clean Up Resources
Delete your test table to close out the lab:
aws dynamodb delete-table --table-name SessionData
Confirm:
aws dynamodb list-tables
Output:
{"TableNames": []}
Wrap-Up
You’ve just implemented automatic data expiration in DynamoDB — no cron jobs, no Lambda functions, no manual deletes.
TTL is perfect for ephemeral data such as sessions, cache entries, or temporary tokens.
By combining TTL with Streams (from Vol. 2) you can even trigger downstream cleanup or analytics pipelines when items expire.
Pro Tip #1 — Use ISO 8601 + Epoch Together
For debugging, store both a human-readable timestamp and the numeric epoch:
"ExpiresAt": {"N": "1731466200"},
"ExpiresISO": {"S": "2025-10-20T21:30:00Z"}
You’ll instantly know what’s expiring when you scan the table.
Pro Tip #2 — Keep TTL Lightweight
TTL is best-effort, not instantaneous. Use it for non-critical cleanup, not precise scheduling.
If you need guaranteed expiry at a specific time, pair TTL with an EventBridge-triggered Lambda.
Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.


Comments
Post a Comment