DynamoDB TTL: Epoch Converter, Setup and the Rules That Bite

Written by Rafal Wilinski
Last updated: October 23rd, 2026
DynamoDB Time to Live automatically deletes expired items, typically within a few days after expiration. Its attribute must be a Number holding Unix epoch seconds; the original deletion consumes no write capacity, but replicated TTL deletes in current global tables are billed in the other Regions. TTL is not supported on multi-Region strongly consistent (MRSC) global tables. The converter checks the timestamp value; you must also store it with the correct DynamoDB type.
Convert a date to a TTL value, or check one
Paste epoch seconds, epoch milliseconds, or a date. You get the number to store, what it means in UTC and in your timezone, how far away it is, and a warning for each thing DynamoDB would reject or misread. The presets fill in a value relative to now.
What DynamoDB expects
The TTL attribute must be a Number holding Unix epoch time in seconds, such as 1758240000. Items whose TTL attribute is any other type, including a numeric string, are skipped by the TTL process and never deleted. A millisecond value is a Number too, so the TTL process accepts it, reads it as seconds, and schedules the item tens of thousands of years out. That item will not expire within the intended retention period.
A TTL more than five years in the past is ignored. Anything between five years ago and now counts as already expired.
There is no minimum. Five minutes from now is a valid TTL.
Getting the current time in seconds is one line in most languages: Math.floor(Date.now() / 1000) in JavaScript, int(time.time()) in Python, System.currentTimeMillis() / 1000L in Java, date +%s in a shell. For the other timestamp formats a table tends to hold, see working with timestamps in DynamoDB.
Enabling TTL
TTL is a table setting: you name the attribute once, and every item that carries a Number in that attribute becomes eligible. The attribute name is case-sensitive and has to match what your code writes. Enabling takes about an hour to reach every partition.
With the CLI
With the CDK
With CloudFormation
In the console
Open the table, choose the Additional settings tab, and turn on Time to Live. The console lets you simulate an expiry date and lists a few items that would match, which is a quick way to confirm the attribute name and the value format before relying on it.
The rules that bite
Expired items are typically deleted within a few days, not immediately. Until then they still come back from a Query or a Scan, and they keep costing storage and read capacity until they go, so filter them out on read. Filtering does not reduce the read capacity already consumed. Note that ttl is a reserved word, so it needs a placeholder:
This filter assumes every returned session needs a TTL. To keep items that intentionally have no expiration, use attribute_not_exists(#ttl) OR #ttl > :now. A GetItem request has no filter expression, so check its returned expiration in application code.
Renaming the attribute means disabling TTL and enabling it again with the new name, and TTL keeps deleting for about half an hour after you disable it. UpdateTimeToLive is not idempotent: calling it while TTL is already on, or twice within an hour, returns a ValidationException, so treat "already enabled" as success in your code.
A table restored from a backup comes back with TTL off. Turn it on again.
TTL deletes consume no write capacity in the Region where the TTL service performs the deletion. In current global tables (version 2019.11.21) using multi-Region eventual consistency (MREC), each replicated delete consumes replicated write capacity in the other replica Regions. Legacy global tables do not replicate TTL deletes. MRSC global tables do not support TTL at all. AWS documents these differences in global-table behavior.
TTL deletes show up in DynamoDB Streams as service deletes, with userIdentity.type set to Service and principalId to dynamodb.amazonaws.com, which is how you archive expired items to S3 or trigger cleanup elsewhere. They are only marked that way in the Region where the delete happened, not in global table replicas. Expired items are also removed from every secondary index, as any delete is.
You can still update an item that has expired but not yet been deleted. Moving its TTL into the future, or removing the attribute, rescues it. Use a condition expression when you do, in case the delete has already happened.
When TTL is the right tool
Session records, one-time tokens, idempotency keys, rate-limit counters, shopping carts, and any event or log row with a retention period. In each case the item's useful life is known when it is written, so the TTL can be written with it and recomputed on every update. That keeps the table lean without a cleanup job or original-Region delete charges. Account for replicated write charges on MREC global tables. For sessions and tokens, enforce expiration when authorizing access; asynchronous physical deletion is not an access-control deadline. The AWS TTL guide describes the deletion behavior.
Frequently Asked Questions
How quickly does DynamoDB TTL delete expired items?
Does DynamoDB TTL use seconds or milliseconds?
Are TTL deletes free on global tables?
Dynobase is a Professional GUI Client for DynamoDB
Start your 7-day free trial today