Monitoring and Operations
Consumer lag, key broker and consumer metrics to alert on, and common operational issues and their causes.
Consumer lag: the single most important number
Consumer lag is the difference between the latest offset written to a partition and a consumer group's last committed offset on that same partition — in plain terms, how far behind the live end of the log that group currently is. Rising, non-recovering lag is usually the earliest and clearest sign that a consumer group can't keep up with production rate, typically visible well before anything actually throws an error or a user notices stale data.
docker exec -it kafka /opt/kafka/bin/kafka-consumer-groups.sh \
--describe --group inventory-service --bootstrap-server localhost:9092
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG
inventory-service orders 0 10482 10600 118
inventory-service orders 1 9921 9921 0
inventory-service orders 2 10310 10850 540
Reading this: partition 2 is 540 messages behind the head of its log — worth investigating specifically (is the consumer instance handling that partition slower than the others? is a downstream dependency it calls being slow? is the partition assignment uneven?), rather than treating "inventory-service has some lag" as one undifferentiated number.
Broker-side metrics worth alerting on
| Metric | What it tells you |
|---|---|
UnderReplicatedPartitions |
Partitions whose replicas have fallen out of sync — an early sign of a struggling broker or a network issue, before anything is actually unavailable |
ActiveControllerCount |
Should be exactly 1 across the whole cluster at all times; 0 or more than 1 signals a controller election problem |
RequestHandlerAvgIdlePercent |
How saturated a broker's request-handling threads are; near 0 means the broker is maxed out |
BytesInPerSec / BytesOutPerSec |
Raw throughput — useful for capacity planning and spotting traffic anomalies |
OfflinePartitionsCount |
Partitions with no available leader at all — actively unavailable, needs immediate attention, not just a leading indicator |
Consumer-side metrics
Beyond raw lag, a few client-side metrics round out the picture: records-lag-max (the worst lag across any single partition the consumer owns, which can hide behind a healthy-looking average), records-consumed-rate (throughput, to correlate against lag trends), fetch-latency-avg (how long the broker is taking to answer fetch requests), and rebalance count/rate — frequent rebalances indicate an unstable consumer group, not routine operation.
Common operational issues and their usual causes
| Symptom | Likely cause |
|---|---|
| Growing, unbounded consumer lag | The consumer is too slow per-record (a slow downstream call), there are too few partitions/consumers for the actual throughput, or an instance in the group is stuck or has silently crashed |
| Frequent consumer group rebalances | The poll loop is exceeding max.poll.interval.ms (slow processing), consumers are crash-looping, or session-timeout settings are too aggressive for the environment |
UnderReplicatedPartitions rising |
A broker under load, disk I/O contention, or a network issue between brokers preventing timely replication |
| Producer seeing frequent timeouts/retries | An overloaded broker, acks=all combined with a slow in-sync replica, or a network issue between the producer and the cluster |
| A spike in duplicate processing downstream | A rebalance occurred mid-batch, exposing the normal at-least-once reprocessing window — worth checking whether the affected consumer's side effects are actually idempotent |
A minimal production monitoring stack
Kafka brokers and clients expose their metrics over JMX by default. The common, well-trodden path is scraping those with a Prometheus JMX exporter, visualizing them in Grafana, and alerting on the thresholds above — consumer lag and UnderReplicatedPartitions first, since they're the two that most reliably catch a real problem before users do.
Common mistakes
- Only checking consumer lag reactively, after users report stale data, instead of alerting on it proactively — by the time it's visibly broken, it's often already been silently growing for a while.
- Treating any rebalance as inherently a problem — an occasional rebalance from a deploy or autoscaling event is normal; the metric that actually signals instability is rebalance frequency, when it's high and continuous rather than an expected, occasional event.
- Not distinguishing "lag is high but shrinking" (a consumer catching up after a blip) from "lag is high and growing" (a consumer that will never catch up without intervention) — the trend matters far more than any single snapshot.
- Ignoring
UnderReplicatedPartitionsbecause "nothing's actually down yet" — it's a leading indicator of reduced fault tolerance, not a cosmetic metric to check only after an outage.