Spring Kafka
Consumer Offset
Runtime Configuration
Message Consumption
Kafka Seek Method

Spring kafka consumer, seek offset at runtime?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Yes, you can seek to a different Kafka offset at runtime in Spring Kafka, but you need to do it through the consumer lifecycle rather than by treating the listener like a random stateless callback. The usual Spring-side tools are ConsumerSeekAware, seek callbacks tied to assigned partitions, or direct access to the underlying Consumer in the right context.

What seeking means

A Kafka consumer maintains a current position per partition. Calling seek changes that position, which means the next poll will start from the offset you specify.

Typical reasons to do this include:

  • replaying messages after an operational incident
  • skipping known-bad records
  • jumping to the beginning or end of a partition
  • implementing controlled reprocessing logic

The important constraint is that seeking only makes sense for partitions currently assigned to that consumer instance.

The Spring Kafka pattern: ConsumerSeekAware

Spring Kafka provides ConsumerSeekAware so a listener can capture seek callbacks when partitions are assigned.

java
1import java.util.Map;
2import java.util.concurrent.ConcurrentHashMap;
3
4import org.springframework.kafka.annotation.KafkaListener;
5import org.springframework.kafka.listener.ConsumerSeekAware;
6import org.springframework.stereotype.Component;
7
8@Component
9public class OrderListener implements ConsumerSeekAware {
10
11    private final Map<String, ConsumerSeekCallback> callbacks = new ConcurrentHashMap<>();
12
13    @KafkaListener(topics = "orders", groupId = "orders-group")
14    public void listen(String payload) {
15        System.out.println("Received: " + payload);
16    }
17
18    @Override
19    public void registerSeekCallback(ConsumerSeekCallback callback) {
20        callbacks.put(Thread.currentThread().getName(), callback);
21    }
22}

That callback gives you a Spring-managed way to request seek operations.

Seeking when partitions are assigned

A very common use is to seek immediately after assignment.

java
1@Override
2public void onPartitionsAssigned(Map<org.apache.kafka.common.TopicPartition, Long> assignments,
3                                 ConsumerSeekCallback callback) {
4    assignments.keySet().forEach(tp -> callback.seek(tp.topic(), tp.partition(), 0));
5}

This forces the consumer to start from offset 0 for each assigned partition. You could also seek to end, to beginning, or to a specific saved offset.

Seeking later at runtime

If you want to trigger seeking based on an API call, admin action, or business event, you need to make sure you are seeking the partitions owned by the listener container that captured the callback.

That is why Spring ties the callback to assignment state. Offset control is not global magic. It is consumer-instance and partition-assignment specific.

In real applications, people often use a service that coordinates with a listener component storing these callbacks, or they use container-level APIs when available.

When direct consumer access is appropriate

Spring Kafka listeners can also expose the native Kafka Consumer in the listener method signature.

java
1import org.apache.kafka.clients.consumer.Consumer;
2import org.springframework.kafka.annotation.KafkaListener;
3
4@KafkaListener(topics = "orders", groupId = "orders-group")
5public void listen(String payload, Consumer<?, ?> consumer) {
6    System.out.println(payload);
7    // consumer.seek(...) can be used carefully here
8}

This is powerful, but it also means you are interacting directly with polling-state machinery. Use it carefully and only when you understand the listener container behavior.

Seeking versus committed offsets

A runtime seek changes the current read position. It does not by itself redefine the long-term committed offset contract unless commits later reflect that new position.

That distinction matters. You can temporarily move the consumer pointer for reprocessing during a session, but group rebalances and restarts interact with committed offsets, not just with one in-memory seek call.

So when people say “seek to another offset,” the operational question is often really:

  • do I want a temporary position change
  • or do I want future consumption to resume from the new point as well

Common Pitfalls

A common mistake is trying to seek partitions that are not assigned to the current consumer instance.

Another mistake is assuming a seek call permanently rewrites committed offsets by itself.

A third mistake is triggering seeks from arbitrary application threads without understanding the listener container and assignment context.

Summary

  • Spring Kafka supports runtime seeking, typically through ConsumerSeekAware.
  • Seek operations only make sense for partitions assigned to the current consumer.
  • You can seek on assignment or later through stored callbacks.
  • Direct native Consumer access is possible but lower level.
  • Distinguish between changing current position and changing what future committed consumption will do.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.