Writing a consumer

Apache Kafka · Essentials · 12 min

Every Kafka-driven service is built around a consumer loop, and its small details decide correctness.

A consumer needs bootstrap.servers and a group.id (the consumer group, covered next). It subscribes to topics and then repeatedly calls poll(timeout), which returns one record or None if nothing arrived in time. Kafka consumers pull: the broker never pushes data, so a slow consumer just falls behind instead of being overwhelmed.

Each returned message may carry an error (for example, end-of-partition events or a deleted topic); check msg.error() before using it. msg.key(), msg.value(), msg.partition(), msg.offset() and msg.timestamp() give the record's contents and position.

Where does a brand-new group start? auto.offset.reset decides when there is no committed offset: latest (the default, only new records) or earliest (from the oldest retained record). Once the group has committed offsets, it resumes from them regardless of this setting.

By default the client auto-commits offsets periodically in the background (every 5 s in librdkafka and Java), which is simple but can lose or repeat records on crashes; later lessons cover manual commits.

Always call close() on shutdown: it commits final offsets and leaves the group immediately, so its partitions are reassigned without waiting for a session timeout. For batch work, consume(num_messages, timeout) returns a list.

Example

import json
from confluent_kafka import Consumer

consumer = Consumer({
    "bootstrap.servers": "localhost:9092",
    "group.id": "billing",
    "auto.offset.reset": "earliest",       # new group: start from the oldest record
})
consumer.subscribe(["orders"])

try:
    while True:
        msg = consumer.poll(1.0)
        if msg is None:
            continue                        # nothing within 1 s
        if msg.error():
            print("error:", msg.error())
            continue
        event = json.loads(msg.value())
        print(msg.partition(), msg.offset(), msg.key().decode(), event["status"])
        # 1 0 c1 created
except KeyboardInterrupt:
    pass
finally:
    consumer.close()                        # commit and leave the group cleanly

Remember

  • Subscribe, then poll in a loop; consumers pull at their own pace
  • Check msg.error() before using a message
  • auto.offset.reset only applies when the group has no committed offset
  • Always close() to commit and leave the group

Watch out for

  • Changing auto.offset.reset to earliest for an existing group and expecting it to re-read history; committed offsets win.

Check yourself

  1. A group with committed offsets restarts with auto.offset.reset=earliest. Where does it start?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kafka.apache.org/43/configuration/consumer-configs/