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 Case | TTL Strategy |
|---|---|
| Session expiration | Set TTL to session timeout (e.g., 24 hours) |
| Temporary data cleanup | Set TTL to data retention period |
| Cache invalidation | Set TTL to cache duration |
| Regulatory data retention | Set TTL to compliance period |
| Soft-delete with cleanup | Set TTL when item is "deleted" |
| One-time tokens | Set 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
- DateTime Formatting — How date and time values are stored
- Table Creation — Creating tables with TTL enabled
- Streams — Processing stream events including TTL deletions