Scenario 02.3.2 · Stuck consumer & max.poll.interval.ms
Kafka max.poll.interval.ms: evicting a stuck consumer
A consumer stuck processing keeps its session alive (it heartbeats) but stops polling - its partitions lag - until max.poll.interval.ms elapses and it leaves the group, handing its partitions to a survivor.
Run this scenario in the playgroundTwo-member group ready. t+0.000s
A 2-partition topic with a cooperative-sticky group of two consumers: c1 owns p0, c2 owns p1. max.poll.interval.ms is 2000 ms. Press play.
Open at this step: step 1, Two-member group readyBoth consuming · lag 0. t+0.900s
One record landed on each partition; c1 drained p0 and c2 drained p1. Both members are caught up.
Open at this step: step 2, Both consuming · lag 0c1 stuck processing · p0 stalls, c2 keeps consuming. t+2.500s
c1 got stuck processing at t=1000. It still heartbeats (its session never times out) and still owns p0, but it no longer polls - so new records on p0 are NOT consumed and its lag grows, while c2 keeps draining p1. Unlike a crash, the member is alive: this is the max.poll.interval.ms failure, not session.timeout.ms.
Open at this step: step 3, c1 stuck processing · p0 stalls, c2 keeps consumingEvicted · survivor took over. t+4.000s
At t=3000 max.poll.interval.ms expired: c1's heartbeat thread left the group (max.poll.interval.ms exceeded) and p0 rebalanced onto the survivor c2, which now owns both partitions and has drained p0 back to lag 0 - the same revoke→assign rebalance a crash eviction uses.
Open at this step: step 4, Evicted · survivor took overWhat you start with
A consumer stuck in processing still sends heartbeats, so session.timeout.ms never fires - but it stops calling poll(). max.poll.interval.ms is the separate guard: when too long passes between polls, the consumer's heartbeat thread leaves the group and its partitions are reassigned to a survivor.
Step by step
- Two-member group ready t+0.000s A 2-partition topic with a cooperative-sticky group of two consumers: c1 owns p0, c2 owns p1. max.poll.interval.ms is 2000 ms. Press play. Open at this step: step 1, Two-member group ready
- Both consuming · lag 0 t+0.900s One record landed on each partition; c1 drained p0 and c2 drained p1. Both members are caught up. Open at this step: step 2, Both consuming · lag 0
- c1 stuck processing · p0 stalls, c2 keeps consuming t+2.500s c1 got stuck processing at t=1000. It still heartbeats (its session never times out) and still owns p0, but it no longer polls - so new records on p0 are NOT consumed and its lag grows, while c2 keeps draining p1. Unlike a crash, the member is alive: this is the max.poll.interval.ms failure, not session.timeout.ms. Open at this step: step 3, c1 stuck processing · p0 stalls, c2 keeps consuming
- Evicted · survivor took over t+4.000s At t=3000 max.poll.interval.ms expired: c1's heartbeat thread left the group (max.poll.interval.ms exceeded) and p0 rebalanced onto the survivor c2, which now owns both partitions and has drained p0 back to lag 0 - the same revoke→assign rebalance a crash eviction uses. Open at this step: step 4, Evicted · survivor took over
The takeaway
Heartbeats prove a consumer is alive; max.poll.interval.ms proves it is making progress - a slow record handler can be evicted for stalling even while it heartbeats normally.
Configs in this scenario
-
max.The longest a group member may go between poll() calls before it counts as failed and the group rebalances its partitions to other members (default 300000, 5 minutes); a static member keeps them until its session times out. How max.poll.interval.ms workspoll. interval. ms -
session.How long the group coordinator waits for a heartbeat from a classic-protocol consumer before it removes the member and rebalances (default 45000, 45 seconds); with group.protocol=consumer the broker group.consumer.session.timeout.ms applies instead. How session.timeout.ms workstimeout. ms
Embed this scenario
Paste this into a blog post, a course page or your team's docs. The scenario plays inside your page, and the link under it points readers to this walkthrough.
<iframe src="https://monedula.dev/kafka-simulator/embed/?scenario=02.3.2" title="Kafka Simulator: Stuck consumer & max.poll.interval.ms" width="100%" height="520" style="border:1px solid #d0d0d0;border-radius:8px" loading="lazy"></iframe>
<p><a href="https://monedula.dev/kafka-simulator/scenarios/max-poll-interval/">Kafka max.poll.interval.ms: evicting a stuck consumer</a></p> Further reading
Troubleshooting
- Kafka consumer group keeps rebalancing: causes and fixes
- Kafka consumer lag keeps growing: causes and fixes
More in Consumer groups
- Kafka consumer poll loop: subscribe, poll, fetch
- Kafka auto.offset.reset: earliest vs latest vs none
- Kafka committed offsets: enable.auto.commit and restart
- Replay a Kafka topic: consumed records stay in the log
- Kafka consumer group: how partitions split across members
- Kafka consumer group rebalance when a consumer joins
- Kafka partition assignors: range vs round-robin vs sticky
- Kafka eager vs cooperative rebalancing (cooperative-sticky)
- Kafka consumer crash and session.timeout.ms
- Kafka static membership: group.instance.id avoids rebalances
- Kafka consumer lag: why it grows and how it drains
- Evicted Kafka consumer: how a survivor takes its partition