View a markdown version of this page

Built-in features (TTL, atomic counters) - AWS SDK for Kotlin

Built-in features (TTL, atomic counters)

DynamoDB Mapper ships with two convenience features that you enable by annotating a property: time-to-live (TTL) and atomic counters. Both are annotation-driven and implemented by interceptors (TtlInterceptor and CounterInterceptor) that the mapper registers by default. You don’t wire anything up; annotating the property is enough.

Note

Because these features rely on the default interceptors, replacing the mapper’s interceptors list outright disables them. Add your own interceptors with += to keep them. See Configure DynamoDB Mapper.

Time-to-live (TTL)

DynamoDB TTL deletes items automatically after an expiration timestamp. Mark a numeric property with @DynamoDbTtlSeconds, passing the item’s lifetime in seconds. Whenever the item is written, the mapper sets that property to the current time plus the lifetime (as an epoch-seconds timestamp):

import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbItem import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbPartitionKey import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbTtlSeconds @DynamoDbItem data class ShoppingCart( @DynamoDbPartitionKey val sessionId: String, val productSkus: List<String>, @DynamoDbTtlSeconds(lifetime = 86_400) var expiresAt: Long, // expires 24 hours after each write )

With this annotation, you don’t compute expiresAt yourself; the mapper populates it on every put, update, batch write, and transactional write.

Note

The annotation makes the mapper write the expiration timestamp, but DynamoDB only deletes expired items if TTL is enabled for that attribute on the table. Enable TTL on the table’s attribute using the DynamoDbClient or the console, as described in Enabling Time to Live. TTL deletions typically occur within a few days of expiration, not immediately.

Atomic counters

An atomic counter is a numeric attribute the mapper increments automatically each time the item is persisted. Mark a numeric property with @DynamoDbCounter:

import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbCounter import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbItem import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbPartitionKey @DynamoDbItem data class Product( @DynamoDbPartitionKey val sku: String, val name: String, val category: String, val priceCents: Long, @DynamoDbCounter var viewCount: Long = 0, var inventory: Long = 0, )

On each mutating operation the mapper increments every counter field by one. For updateItem, it adds an if_not_exists(field, 0) + 1 clause to the update expression, so a counter starts at zero even if the attribute doesn’t exist yet.

Keep these caveats in mind:

  • The counter advances by one on every persist of the item, so it reflects how many times the item has been written, not a value you set. Let the mapper manage it rather than assigning it yourself.

  • Counters increment by a fixed step of one; for arbitrary increments or decrements, use an update expression (add { attr["…​"] += n }) instead.