Skip to content

How Kafka consumer lag actually works

Consumer lag is the most-watched Kafka health signal, and also the most misunderstood. This guide explains what lag actually is, mechanically, so the metrics make sense.

Every message in a Kafka partition has a monotonically increasing offset — 0, 1, 2, and so on. Offsets are per-partition, not per-topic. Two things move along this ruler:

  • Log-end offset (LEO): the offset of the next message a producer will write. It’s the “head” of the partition — how far production has reached.
  • Committed offset: the offset a consumer group has recorded as processed, stored in the internal __consumer_offsets topic. It’s how far consumption has reached.

Consumer lag for one partition is simply:

lag = log-end offset − committed offset

If the log-end offset is 1,000 (producers have written through offset 999) and the group has committed offset 950, the group is 50 messages behind on that partition.

A consumer group subscribes to topics, and each topic has partitions. Lag is measured per partition, then rolled up:

  • Per group + topic: sum of partition lags (total backlog), plus max (the worst partition).
  • Per group: sum across all its topics.

This matters because a group can look “fine” on total lag while one partition is badly behind — a hot partition or a stuck assignment. Klag exposes both the per-partition series and the aggregates so you can drill in. See the Metrics Overview for the exact metric names (klag_consumer_lag, klag_consumer_lag_sum, klag_consumer_lag_max).

The committed offset reflects what the consumer has committed, which depends on the commit strategy (auto-commit interval, or manual commit after processing). With auto-commit, a consumer can commit an offset slightly ahead of what it has fully processed. Lag is therefore a close proxy for “unprocessed messages,” not a cryptographic guarantee. For most alerting this distinction doesn’t matter; for exactly-once reasoning it does.

“50,000 messages behind” means nothing without throughput. At 50,000 msg/s it’s one second of backlog; at 50 msg/s it’s a growing incident. That’s why message-count lag alone is a weak signal — see Why monitoring lag value alone isn’t enough.

A lag exporter like Klag never joins the consumer group. It uses the Kafka Admin API (read-only, DESCRIBE) to fetch each group’s committed offsets and each partition’s log-end offset, subtracts, and reports. No messages are consumed, no offsets are written. See ACL Permissions for the exact grants.