Kafka Streams 3.5.0 fetchAll API: missing pagination for large state stores
0 reputation · 05 Feb 2023, 11:31 UTC
0 reputation · 05 Feb 2023, 11:31 UTC
Developers need a way to iterate over all key‑value pairs in a queryable state store while keeping memory usage bounded, especially when the store contains millions of entries.
The fetchAll method introduced in Kafka Streams 3.5.0 returns a List containing the complete store contents, providing no offset‑based pagination or streaming alternative. Invoking fetchAll on a large store can exhaust the JVM heap and increase latency.
It is unclear whether the Kafka Streams roadmap includes a paginated fetch API, and what the community‑endorsed pattern is for safely traversing large state stores without triggering out‑of‑memory errors.
Is there a planned enhancement to add paginated fetch methods to QueryableStore? If not, what architectural approach should be used to page through a state store safely? Are there any interim solutions, such as custom key range queries, that are officially supported?
33775 reputation · 05 Feb 2023, 12:39 UTC
The fetchAll method introduced in Kafka Streams 3.5.0 returns a List that contains the entire contents of a queryable state store. It has no built‑in pagination or streaming interface. There is no publicly documented roadmap entry for a paginated fetch API in the current 3.5.x series, and the official Javadoc for QueryableStore and KeyValueStore makes no mention of such an enhancement.
fetchAll() on a store with millions of entries can exhaust the JVM heap and increase latency.KeyValueStore interface provides an all() method that returns a KeyValueIterator, which streams results lazily.KeyValueIterator can be processed in batches and must be closed after use to avoid resource leaks.Use the all() iterator to read the store sequentially, and wrap it in a simple pagination helper that returns a fixed‑size batch on each call. This keeps memory usage bounded and avoids OOM.
public class PaginatedStoreReader<K, V> {
private final KeyValueIterator<K, V> iterator;
private final int batchSize;
public PaginatedStoreReader(KeyValueStore<K, V> store, int batchSize) {
this.iterator = store.all();
this.batchSize = batchSize;
}
public List<KeyValue<K, V>> nextBatch() {
List<KeyValue<K, V>> batch = new ArrayList<>(batchSize);
int count = 0;
while (iterator.hasNext() && count < batchSize) {
batch.add(iterator.next());
count++;
}
return batch;
}
public void close() { iterator.close(); }
}
Typical usage:
PaginatedStoreReader<String, Integer> reader =
new PaginatedStoreReader<>(store, 10_000);
try {
List<KeyValue<String, Integer>> batch;
while (!(batch = reader.nextBatch()).isEmpty()) {
// process batch
}
} finally {
reader.close();
}
String or Long), you can open the iterator and skip entries until a desired start key, then read a limited number of entries. This is linear in the offset and not efficient for deep pagination.At this time, the Kafka community has not opened an issue to add a paginated fetch API to QueryableStore. If your use case requires deep pagination or random page access, consider filing an issue on the Apache Kafka issue tracker and provide a concrete use case. Until then, the iterator‑based approach is the recommended pattern.
Do you need to support random page jumps (e.g., page 10 of 100) or only forward sequential reads? This determines whether a simple iterator wrapper suffices or you need an auxiliary index.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.