[[redis.repositories.expirations]]
= Time To Live

Objects stored in Redis may be valid only for a certain amount of time.
This is especially useful for persisting short-lived objects in Redis without having to remove them manually when they reach their end of life.
The expiration time in seconds can be set with `@RedisHash(timeToLive=...)` as well as by using `KeyspaceSettings` (see xref:redis/redis-repositories/keyspaces.adoc[Keyspaces]).

More flexible expiration times can be set by using the `@TimeToLive` annotation on either a numeric property or a method.
However, do not apply `@TimeToLive` on both a method and a property within the same class.
The following example shows the `@TimeToLive` annotation on a property and on a method:

.Expirations
====
[source,java]
----
public class TimeToLiveOnProperty {

  @Id
  private String id;

  @TimeToLive
  private Long expiration;
}

public class TimeToLiveOnMethod {

  @Id
  private String id;

  @TimeToLive
  public long getTimeToLive() {
  	return new Random().nextLong();
  }
}
----
====

NOTE: Annotating a property explicitly with `@TimeToLive` reads back the actual `TTL` or `PTTL` value from Redis. -1 indicates that the object has no associated expiration.

The repository implementation ensures subscription to https://redis.io/topics/notifications[Redis keyspace notifications] via `RedisMessageListenerContainer`.

When the expiration is set to a positive value, the corresponding `EXPIRE` command is run.
In addition to persisting the original, a phantom copy is persisted in Redis and set to expire five minutes after the original one.
This is done to enable the Repository support to publish `RedisKeyExpiredEvent`, holding the expired value in Spring's `ApplicationEventPublisher` whenever a key expires, even though the original values have already been removed.
Expiry events are received on all connected applications that use Spring Data Redis repositories.

By default, the key expiry listener is disabled when initializing the application.
The startup mode can be adjusted in `@EnableRedisRepositories` or `RedisKeyValueAdapter` to start the listener with the application or upon the first insert of an entity with a TTL.
See https://docs.spring.io/spring-data/redis/docs/{version}/api/org/springframework/data/redis/core/RedisKeyValueAdapter.EnableKeyspaceEvents.html[`EnableKeyspaceEvents`] for possible values.

The `RedisKeyExpiredEvent` holds a copy of the expired domain object as well as the key.

NOTE: Delaying or disabling the expiry event listener startup impacts `RedisKeyExpiredEvent` publishing.
A disabled event listener does not publish expiry events.
A delayed startup can cause loss of events because of the delayed listener initialization.

NOTE: The keyspace notification message listener alters `notify-keyspace-events` settings in Redis, if those are not already set.
Existing settings are not overridden, so you must set up those settings correctly (or leave them empty).
Note that `CONFIG` is disabled on AWS ElastiCache, and enabling the listener leads to an error.
To work around this behavior, set the `keyspaceNotificationsConfigParameter` parameter to an empty string.
This prevents `CONFIG` command usage.

NOTE: Redis Pub/Sub messages are not persistent.
If a key expires while the application is down, the expiry event is not processed, which may lead to secondary indexes containing references to the expired object.

NOTE: `@EnableKeyspaceEvents(shadowCopy = OFF)` disable storage of phantom copies and reduces data size within Redis. `RedisKeyExpiredEvent` will only contain the `id` of the expired key.

