Monedula

Scenario 13.2.1 · Reset offsets the right way

Reset Kafka consumer group offsets with --to-earliest

Terminal ops · Intermediate · about 3 min · Apache Kafka 4.3

A reset is stop, reset, start: it refuses a live group whether or not you pass --execute, the dry run is the default, and the replay is visible on the canvas.

Run this scenario in the playground

Back at the bottom of the log. t+4.400s

The reset landed and the first commit after it has settled, so there is a number to read again: `kafka-consumer-groups --describe --group g1` has the group down near the START of a log it had already finished, with LAG most of the way back up. `kafka-get-offsets --topic orders --time earliest` says why that is where it went - nothing has been deleted, so the earliest offset in this log is still 0.

Open at this step: step 4, Back at the bottom of the log

What you start with

This scenario is played from the terminal (Ctrl and the backtick key). Resetting a consumer group is the most common destructive-looking operation on a running Kafka cluster, and the tool refuses to do it while the group still has a live member - for good reason. Here the group reads a topic, the consumer is stopped, the reset runs, and the group replays the whole log from the beginning.

Step by step

  1. One group, one member, nothing to read t+0.000s Open the terminal with Ctrl and the backtick key (on a phone, the "..." menu). `kafka-consumer-groups --list` finds the one group, and `kafka-consumer-groups --describe --group g1` shows it before a single record exists: one member owns the partition, the log end is zero, and CURRENT-OFFSET and LAG read as dashes because this group has never committed anything. Open at this step: step 1, One group, one member, nothing to read
  2. Eight records read, and a reset that will not run t+3.000s `kafka-consumer-groups --describe --group g1` shows the group level with the end of the log. Now try the reset twice and read the ANSWER rather than the flag: `kafka-consumer-groups --reset-offsets --group g1 --topic orders --to-earliest --dry-run` and `kafka-consumer-groups --reset-offsets --group g1 --topic orders --to-earliest --execute` are refused with the same line, because the group's state is checked before any plan is computed. Open at this step: step 2, Eight records read, and a reset that will not run
  3. The consumer is stopped, so the group is Empty t+3.600s `kafka-consumer-groups --describe --group g1 --state` now reports Empty with no members, and `kafka-consumer-groups --describe --group g1` shows the committed offsets the stopped app left behind. The same dry run is allowed here: `kafka-consumer-groups --reset-offsets --group g1 --topic orders --to-earliest --dry-run` prints the offset it WOULD write and changes nothing, which is what you get when you leave the flag off. Then `kafka-consumer-groups --reset-offsets --group g1 --topic orders --to-earliest --execute` does it for real - and the scenario does exactly that on the next tick, so pressing it forks the sandbox onto the same three actions. Open at this step: step 3, The consumer is stopped, so the group is Empty
  4. Back at the bottom of the log t+4.400s The reset landed and the first commit after it has settled, so there is a number to read again: `kafka-consumer-groups --describe --group g1` has the group down near the START of a log it had already finished, with LAG most of the way back up. `kafka-get-offsets --topic orders --time earliest` says why that is where it went - nothing has been deleted, so the earliest offset in this log is still 0. Open at this step: step 4, Back at the bottom of the log
  5. Climbing back up t+4.600s One poll later the group has moved: `kafka-consumer-groups --describe --group g1` shows CURRENT-OFFSET higher and LAG smaller than on the previous frame, which is the replay in progress. `kafka-consumer-groups --describe --group g1 --members --verbose` shows the member owning the same partition. The simulator brings back the same member id; a real restarted consumer joins with a new one (only a static group.instance.id carries over). The reset itself rewrites committed offsets and nothing else. Open at this step: step 5, Climbing back up
  6. Back at the end of the log, the long way round t+5.400s The replay is finished and `kafka-consumer-groups --describe --group g1` reads exactly as it did before the reset. `kafka-get-offsets --topic orders --time latest` asks the log itself where it ends, with no consumer group involved, and answers with the same number the lag table's LOG-END-OFFSET column is showing. Open at this step: step 6, Back at the end of the log, the long way round
  7. Reading live again t+6.800s A ninth record arrived after the replay and the group consumed it in stride. `kafka-consumer-groups --describe --group g1` has LAG back at zero against a log end one record higher, and `kafka-consumer-groups --describe --group g1 --state` is Stable with one member - the group is doing its normal job again, from an offset you chose. Open at this step: step 7, Reading live again

The takeaway

A reset is stop, reset, start. The tool will not do the stopping for you: it checks the group state first, and a group with any live member is refused before a plan is even computed, so passing --execute changes nothing about that answer. Once the group is Empty the same command prints the offsets it would move - that is the DEFAULT, and it is free - and only --execute writes the new offsets - here the sandbox also brings the member back in the same step, where on a real cluster you restart the application yourself. What the canvas then shows is a genuine replay: the group re-reads every record it had already committed, and carries straight on into the new ones.

Configs in this scenario

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=13.2.1" title="Kafka Simulator: Reset offsets the right way" width="100%" height="520" style="border:1px solid #d0d0d0;border-radius:8px" loading="lazy"></iframe>
<p><a href="https://monedula.dev/kafka-simulator/scenarios/reset-offsets/">Reset Kafka consumer group offsets with --to-earliest</a></p>

Further reading

Apache Kafka documentation

More in Terminal ops

All scenarios