Skip to main content

TTL Support

Configure Time-To-Live for automatic item expiration in DynamoDB.

Overview

DynamoDB's Time-To-Live (TTL) feature automatically deletes items after a specified timestamp. FluentDynamoDB supports TTL through the [TimeToLive] attribute and table creation options.

How TTL Works

  • You designate a numeric attribute as the TTL attribute
  • The attribute value must be a Unix epoch timestamp (seconds since January 1, 1970)
  • DynamoDB automatically deletes items whose TTL timestamp is older than the current time
  • Deletions happen in the background and don't consume write capacity
  • Deleted items may still appear in queries for up to 48 hours after expiration

Defining TTL on Entities

Use the [TimeToLive] attribute on a DateTime? property:

[DynamoDbTable("sessions")]
public partial class Session
{
[PartitionKey]
[DynamoDbAttribute("pk")]
public string SessionId { get; set; } = string.Empty;

[DynamoDbAttribute("userId")]
public string UserId { get; set; } = string.Empty;

/// <summary>
/// Items will be automatically deleted after this timestamp.
/// </summary>
[TimeToLive]
[DynamoDbAttribute("ttl")]
public DateTime? ExpiresAt { get; set; }
}

The source generator automatically converts DateTime values to Unix epoch seconds when writing to DynamoDB and back to DateTime when reading.

Setting TTL Values

// Session expires in 24 hours
var session = new Session
{
SessionId = "sess-123",
UserId = "user-456",
ExpiresAt = DateTime.UtcNow.AddHours(24)
};

await table.Sessions.PutAsync(session);

// Session expires in 7 days
session.ExpiresAt = DateTime.UtcNow.AddDays(7);
await table.Sessions.PutAsync(session);

// Remove TTL (item won't expire)
session.ExpiresAt = null;
await table.Sessions.PutAsync(session);

Table Creation with TTL

When creating tables programmatically (e.g., for integration tests), enable TTL:

using Oproto.FluentDynamoDb.Provisioning;

var result = await SessionsTable.CreateTableAsync(
client,
"test-sessions-table",
new TableCreationOptions { EnableTtl = true });

Processing TTL Deletions in Streams

When items are deleted by TTL, DynamoDB emits a REMOVE event in the stream. The Streams package can distinguish TTL deletions from manual deletions:

using Oproto.FluentDynamoDb.Streams;

await record.Process<Session>()
.OnTtlDelete(async (session, _) =>
{
// Session expired automatically
await _auditLog.LogSessionExpiry(session.UserId);
})
.OnNonTtlDelete(async (session, _) =>
{
// User explicitly logged out
await _auditLog.LogLogout(session.UserId);
await _notificationService.SendLogoutConfirmation(session.UserId);
})
.ProcessAsync();

TTL deletions are identified by checking UserIdentity.Type == "Service" and UserIdentity.PrincipalId == "dynamodb.amazonaws.com" on the stream record.

Use Cases

Use CaseTTL Strategy
Session expirationSet TTL to session timeout (e.g., 24 hours)
Temporary data cleanupSet TTL to data retention period
Cache invalidationSet TTL to cache duration
Regulatory data retentionSet TTL to compliance period
Soft-delete with cleanupSet TTL when item is "deleted"
One-time tokensSet TTL to token validity period

Best Practices

  • Always use DateTime? (nullable) so you can opt items out of TTL by setting null
  • Use UTC timestamps to avoid timezone issues
  • DynamoDB checks TTL approximately every 24 hours — items may persist slightly beyond their TTL
  • TTL deletions don't consume write capacity units
  • Enable DynamoDB Streams if you need to react to TTL expirations

See Also