Skip to content
Mark Lauter edited this page May 16, 2026 · 4 revisions

TTL (Time to Live)

Overview

DynamoDbLite supports DynamoDB's Time to Live feature. When enabled, items with an expired TTL epoch are filtered out of all read operations and periodically cleaned up in the background. See DynamoDB TTL in the AWS docs.

Enabling TTL

Use UpdateTimeToLiveAsync to enable TTL on a table. Specify the attribute name that holds the expiration timestamp (Unix epoch in seconds).

await client.UpdateTimeToLiveAsync(new UpdateTimeToLiveRequest
{
    TableName = "Sessions",
    TimeToLiveSpecification = new TimeToLiveSpecification
    {
        Enabled = true,
        AttributeName = "ExpiresAt"
    }
});

When TTL is enabled, DynamoDbLite scans all existing items, populates the internal ttl_epoch column from the specified attribute, and backfills the same epoch into every index table — all in the same call.

Disabling TTL

await client.UpdateTimeToLiveAsync(new UpdateTimeToLiveRequest
{
    TableName = "Sessions",
    TimeToLiveSpecification = new TimeToLiveSpecification
    {
        Enabled = false,
        AttributeName = "ExpiresAt"
    }
});

When disabled, all ttl_epoch values are cleared to NULL (items are no longer filtered by TTL).

Checking TTL status

var response = await client.DescribeTimeToLiveAsync("Sessions");
Console.WriteLine(response.TimeToLiveDescription.TimeToLiveStatus); // ENABLED or DISABLED
Console.WriteLine(response.TimeToLiveDescription.AttributeName);     // "ExpiresAt" or null

Signatures

Task<DescribeTimeToLiveResponse> DescribeTimeToLiveAsync(string tableName, CancellationToken ct = default)
Task<DescribeTimeToLiveResponse> DescribeTimeToLiveAsync(DescribeTimeToLiveRequest request, CancellationToken ct = default)
Task<UpdateTimeToLiveResponse> UpdateTimeToLiveAsync(UpdateTimeToLiveRequest request, CancellationToken ct = default)

TTL attribute format

The TTL attribute must be a number (N) attribute containing a Unix epoch timestamp in seconds:

await client.PutItemAsync("Sessions", new Dictionary<string, AttributeValue>
{
    ["SessionId"] = new() { S = "sess-123" },
    ["UserId"] = new() { S = "user-1" },
    ["ExpiresAt"] = new() { N = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds().ToString() }
});

Items where the TTL attribute is missing, not a number, or not parseable are treated as having no TTL (they never expire).

Read-time filtering

All read operations automatically filter out expired items:

  • GetItemAsync — returns a response with an empty Item (same shape as a missing item)
  • QueryAsync / ScanAsync — excludes expired items from results
  • BatchGetItemAsync — excludes expired items
  • TransactGetItemsAsync — excludes expired items

The filter is unconditional: (ttl_epoch IS NULL OR ttl_epoch >= @nowEpoch). Items without a TTL epoch (NULL) are always included.

Background cleanup

After read operations, DynamoDbLite triggers a fire-and-forget background task to physically delete expired items. This cleanup is throttled to at most once every 30 seconds per table.

The cleanup:

  1. Deletes expired rows from the items table
  2. Deletes expired rows from all index tables
  3. Updates the table's item count and size statistics

Validation

  • TimeToLiveSpecification.Enabled must be true or false — any other value (including null) throws AmazonDynamoDBException
  • Enabling TTL when already enabled throws AmazonDynamoDBException
  • Disabling TTL when already disabled throws AmazonDynamoDBException
  • AttributeName is required when enabling

Parity notes

Behavior DynamoDB DynamoDbLite
Deletion timing ~48 hours after expiry Filtered instantly at read time; physical deletion within 30 seconds
Deletion visibility Expired items may still appear Expired items are never returned
Enable/disable latency Can take up to 1 hour Immediate
Backfill on enable Not applicable Scans all items and populates ttl_epoch
DynamoDB Streams Emits deletion events Not supported (no streams)

Next steps

Clone this wiki locally