---
title: "State TTL for Apache Flink: How to Limit the Lifetime of State"
description: "Introduces the state time-to-live (TTL) feature that Apache Flink added in 1.6.0 for expiring keyed state, for example to meet GDPR or to limit state size. Shows a StateTtlConfig example with Duration, the TTL options, and how expired state is cleaned up on read, in full snapshots and in the background."
lastUpdated: 2026-10-14T09:41:47.000Z
source_url:
  html: "https://www.ververica.com/developers/flink-state-ttl"
  md: "https://www.ververica.com/developers/flink-state-ttl.md"
---

A common requirement for many stateful streaming applications is the ability to control how long application state can be accessed (e.g., due to legal regulations like GDPR) and when to discard it. This blog post introduces the state time-to-live (TTL) feature that was added to Apache Flink with the 1.6.0 release.

We outline the motivation and discuss use cases for the new State TTL feature. Moreover, we show how to use and configure it and explain how Flink internally manages state with TTL.

![Title graphic: State TTL, how to limit the lifetime of state in Apache Flink, with a stopwatch and the Flink squirrel](https://cdn.sanity.io/images/6b38iw1w/production/ec5dcea06229040f4f15d941e057ad03531a115c-950x568.webp)

## Introduction to Stateful Stream Processing with Apache Flink

Any non-trivial real-time streaming application includes stateful operations. Apache Flink provides many powerful features for fault-tolerant [stateful stream processing](https://www.ververica.com/ecosystem-introduction/stream-processing-with-apache-flink-beginners-guide). Users can choose from different state primitives (atomic value, list, map) and backends (heap memory, RocksDB) that maintain the state. Application logic in processing functions can access and modify the state. Typically, the state is associated with a key, allowing for scalable processing and storage similar to key/value stores. Apache Flink transparently manages the distribution of state (including support for scaling out or in) and periodically performs checkpoints to be able to recover jobs in case of a failure with exactly-once state consistency guarantees.

In the remainder of this blog post, we use the example of a stateful application that ingests a stream of user login events and stores for each user the time of the last login to improve the experience of frequent visitors.

## The Transient Nature of State

There are two major reasons why state should be maintained only for a limited time.

- **Complying with data protection regulations**

Recent developments around data privacy regulations, such as the new General Data Protection Regulation (GDPR) introduced by the European Union, make compliance with such data requirements an important topic in the IT industry. Especially the requirement for keeping data for a limited amount of time and preventing access to it thereafter is a common challenge for companies that provide short-term services to their customers and process their personal data. In our application that stores the time of the last login, it would not be acceptable to keep the information forever to prevent an unnecessary insight into the user’s privacy. Consequently, the application would need to remove the information after a certain period of time. The same applies to the customer profiles that banks keep as streaming state for [real-time personalization](https://www.ververica.com/banking/customer-personalization).

- **Managing the size of state storage more efficiently**

Another concern is the ever-growing size of state storage. Oftentimes, data needs to be persisted temporarily while there is some user activity around it, e.g. web sessions. When the activity ends there is no longer interest in that data while it still occupies storage. The application has to take extra actions and explicitly remove the useless state to clean up the storage. Following our previous example of storing the time of the last login, it might not be necessary after some time because the user can be treated as “infrequent” later on.

Both requirements can be addressed by a feature that “magically” removes the state for a key once it must not be accessed anymore or once it is not valuable enough to keep it in the storage.

## What Can We Do About It?

The 1.6.0 release of Apache Flink introduced the State TTL feature. Developers of stream processing applications can configure the state of operators to expire if it has not been touched within a certain period of time (time-to-live). The expired state is later garbage-collected by a lazy clean-up strategy.

In Flink’s DataStream API, application state is defined by a [state descriptor](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/fault-tolerance/state/#using-keyed-state). State TTL is configured by passing a StateTtlConfig to a state descriptor. The following **Java example **shows how to create a state TTL configuration and provide it to the state descriptor that holds the last login time of a user as a Long value:

```java
import org.apache.flink.api.common.state.StateTtlConfig;
import java.time.Duration;
import org.apache.flink.api.common.state.ValueStateDescriptor;
StateTtlConfig ttlConfig = StateTtlConfig
   .newBuilder(Duration.ofDays(7))
   .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
   .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
   .build();
ValueStateDescriptor<Long> lastUserLogin = new ValueStateDescriptor<>("lastUserLogin", Long.class);
lastUserLogin.enableTimeToLive(ttlConfig);
```

Flink provides multiple options to configure the behavior of the state TTL functionality.

1. **When is the Time-to-Live reset?**
1. By default, the expiration time of a state entry is updated when the state is modified. Optionally, it can also be updated on read access at the cost of an additional write operation to update the timestamp.
1. **Which time semantics are used for the Time-to-Live timers?**
1. With Flink 1.6.0, users can only define a state TTL in terms of processing time.
1. **Can the expired state be accessed one last time?**
1. Let’s assume that some state has expired but it is still available in storage and has not been removed yet. If this state is being read out, the user can set different visibility types for its value. In both cases, the state is subsequently removed.
- The first option is to never return the expired state. This way the state is hidden from the user and does not exist anymore which prevents from accessing any personal data after the required period of time.
- The second available option is to return expired-but-not-yet-garbage-collected state. This alternative addresses applications where eventual storage cleanup is important but the application can make some use of the still available, but expired state.

You can read more about how to use state TTL [in the Apache Flink documentation](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/fault-tolerance/state/#state-time-to-live-ttl).

Internally, the State TTL feature is implemented by storing an additional timestamp of the last modification along with the user value in this case. While this approach adds some storage overhead, it allows Flink to check for the expired state during state access, checkpointing, recovery, or dedicated storage cleanup procedures.

## “Taking out the Garbage”

When a state object is accessed in a read operation, Flink will check its timestamp and clear the state if it is expired (depending on the configured state visibility, the expired state is returned or not). Due to this lazy removal, expired state that is never accessed again will forever occupy storage space unless it is garbage collected.

So how can the expired state be removed without the application logic explicitly taking care of it? In general, there are different possible strategies to remove it in the background.

Flink 1.6.0 supports automatic eviction of the expired state when a full snapshot for a checkpoint or savepoint is taken. Note that state eviction is not applied for incremental checkpoints. State eviction on full snapshots must be explicitly enabled as shown in the following example:

```java
StateTtlConfig ttlConfig = StateTtlConfig
   .newBuilder(Duration.ofDays(7))
   .cleanupFullSnapshot()
   .build();
```

The local storage stays untouched at the moment but the size of the stored snapshot is reduced. The local state of an operator will only be cleaned up, when the operator reloads its state from a snapshot, i.e., in case of a recovery or when starting from a savepoint.

Since Flink 1.10, expired state is also cleaned up in the background by default: the heap state backend relies on incremental cleanup and the RocksDB state backend uses a compaction filter (see [Cleanup of Expired State](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/fault-tolerance/state/#cleanup-of-expired-state) in the Flink documentation).

## Summary

Time-based state access restrictions and automatic state clean-up are common challenges in the world of stateful stream processing. With its 1.6.0 release, Apache Flink introduces the first implementation of State TTL support to tackle these problems. In the current version, State TTL guarantees state inaccessibility after a configured timeout to comply with GDPR or any other data compliance rules.

## Frequently Asked Questions

### What is state TTL in Apache Flink?

State time-to-live (TTL) in Apache Flink lets developers configure operator state to expire if it has not been touched within a certain period of time. The expired state is later garbage-collected by a lazy clean-up strategy. The feature was added with the Flink 1.6.0 release.

### Why should state have a limited lifetime in Flink applications?

There are two main reasons to keep Flink state only for a limited time: complying with data protection regulations such as GDPR, which require keeping personal data for a limited time, and managing the ever-growing size of state storage.

### How do you configure state TTL in the Flink DataStream API?

In Flink's DataStream API, state TTL is configured by passing a StateTtlConfig to the state descriptor that defines the application state.

### When is the state TTL reset in Apache Flink?

By default, the expiration time of a Flink state entry is updated when the state is modified. Optionally, it can also be updated on read access, at the cost of an additional write operation to update the timestamp.

### How is expired state cleaned up in Apache Flink?

Flink clears expired state lazily when it is read, and since Flink 1.6.0 it can also evict expired state when a full snapshot for a checkpoint or savepoint is taken, though not for incremental checkpoints. Since Flink 1.10, expired state is also cleaned up in the background by default: the heap state backend uses incremental cleanup and the RocksDB state backend uses a compaction filter.