FREE TOOL

DynamoDB TTL Converter

Convert DynamoDB TTL epoch timestamps to dates and back, catch values in milliseconds that never expire, and get the code to set TTL in CLI, JS and Python.

  • Your data never leaves your browser: everything is calculated by JavaScript on this page, not on a server.
  • Nothing you enter is uploaded, processed on a server or stored. Check it in your browser's developer tools (Network tab).
  • Once the page has loaded, the tool works without an internet connection.

Timestamp or date

Epoch seconds, milliseconds or microseconds - told apart by the number of digits - or a date such as 2027-01-01T00:00:00Z.

Or expire after

The usual TTL: a time from now. The code below then computes it the same way.

Your table optional

Used in the code below.

See result ↓

Set it

# Turn TTL on for the table, once
aws dynamodb update-time-to-live --table-name YourTable \
    --time-to-live-specification 'Enabled=true, AttributeName=expireAt'

# 2027-01-01T00:00:00.000Z
EXPIRE_AT=1798761600

aws dynamodb update-item --table-name YourTable \
    --key '{"id": {"S": "item-id"}}' \
    --update-expression 'SET #ttl = :ttl' \
    --expression-attribute-names '{"#ttl": "expireAt"}' \
    --expression-attribute-values '{":ttl": {"N": "'"$EXPIRE_AT"'"}}'
import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
import {DynamoDBDocumentClient, UpdateCommand} from '@aws-sdk/lib-dynamodb';

const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));

// Seconds, not milliseconds: Date.now() is in milliseconds.
const expireAt = 1798761600; // 2027-01-01T00:00:00.000Z

await client.send(new UpdateCommand({
  TableName: "YourTable",
  Key: {id: 'item-id'},
  UpdateExpression: 'SET #ttl = :ttl',
  ExpressionAttributeNames: {'#ttl': "expireAt"},
  ExpressionAttributeValues: {':ttl': expireAt},
}));
import boto3

table = boto3.resource('dynamodb').Table("YourTable")

# A whole number of seconds: time.time() has a fraction, int() drops it.
expire_at = 1798761600  # 2027-01-01T00:00:00.000Z

table.update_item(
    Key={'id': 'item-id'},
    UpdateExpression='SET #ttl = :ttl',
    ExpressionAttributeNames={'#ttl': "expireAt"},
    ExpressionAttributeValues={':ttl': expire_at},
)
TTL and DynamoDB Streams are typical AWS Developer Associate exam questionsTry free DVA-C02 practice questions with answers and explanations.DVA-C02 questions →

How DynamoDB TTL works

Time to Live (TTL) deletes items for you once they are no longer needed - sessions, tokens, caches, logs. You turn it on for a table and name one attribute; every item with that attribute expires at the moment it holds. The value has to be:

  • a Number (N) - a string with the same digits is ignored;
  • in Unix epoch seconds, the number of seconds since 1970-01-01 00:00:00 UTC - for example 1798761600 for 2027-01-01 00:00 UTC;
  • no more than five years in the past - older values are ignored.

An item without the attribute, or with a value that breaks one of these rules, is simply never deleted. There is no error and no warning.

What happensDetails
When the item is deletedAt any time after it expires, typically within a few days - not at the exact second.
Cost of the deleteNone: TTL deletes consume no write capacity. In a global table, the deletes replicated to other Regions do consume replicated writes.
Secondary indexesThe item is removed from local and global secondary indexes, like any delete.
DynamoDB StreamsThe delete appears as a service delete, with userIdentity.type "Service" and userIdentity.principalId "dynamodb.amazonaws.com".

The milliseconds mistake: items that never expire

The most common TTL bug is a value in milliseconds. JavaScript's Date.now() and Java's System.currentTimeMillis() return milliseconds, so 1798761600000 ends up in the attribute. DynamoDB reads it as seconds - a date around the year 58,970 - and the item stays forever. The converter above flags such values: seconds have 10 digits today, milliseconds 13.

LanguageCurrent time in epoch seconds
JavaScriptMath.floor(Date.now() / 1000)
Pythonint(time.time())
JavaInstant.now().getEpochSecond()
Gotime.Now().Unix()
C#DateTimeOffset.UtcNow.ToUnixTimeSeconds()
Shelldate +%s

Add the lifetime in seconds: 90 * 24 * 60 * 60 for 90 days. Recompute it on every update if items should live 90 days from their last change rather than from their creation.

Expired items still show up in reads

Until the background process deletes an expired item, Query, Scan and GetItem return it, and it still counts towards storage and read costs. When expired data must not be used, filter it out by comparing the TTL attribute with the current time:

FilterExpression: #ttl > :now
ExpressionAttributeNames: {"#ttl": "expireAt"}
ExpressionAttributeValues: {":now": 1790000000}

The same comparison as a ConditionExpression keeps a write from touching an expired item. Build either with the DynamoDB expression builder. Setting the attribute to a future time, or removing it, before the item is deleted keeps the item.

Turning TTL on

In the DynamoDB console: the table's Additional settings, Time to Live, Turn on, and the attribute name. With the AWS CLI:

aws dynamodb update-time-to-live --table-name YourTable \
    --time-to-live-specification 'Enabled=true, AttributeName=expireAt'

A table has one TTL attribute. It does not have to exist in any item yet, and items without it are never deleted by TTL.

Frequently asked questions

Why are my expired items not deleted?

Check, in this order: TTL is turned on for the table with the same attribute name; the value is a Number, not a string; it is in seconds, not milliseconds; it is less than five years in the past. If all of that holds, wait: deletion typically happens within a few days after the expiry.

Can the TTL attribute hold a date string such as 2027-01-01?

No. TTL takes only a Number in epoch seconds; an item whose TTL attribute is a string is never deleted. Convert the date above and store the number.

Does TTL delete items at the exact expiry time?

No. Expired items are deleted in the background, typically within a few days. If an application must not see them, filter by the TTL attribute in reads.

Is the timestamp sent anywhere?

No. The conversion runs in your browser: nothing you enter is uploaded, processed on a server or stored. The page only counts that the converter was used and what kind of value it got, never the value.

References

Using time to live (TTL) in DynamoDB
Computing time to live (TTL) in DynamoDB
Working with expired items and time to live (TTL)