5 - Kafka Producer and Consumer Flow
Producer Write Flow
Imagine a producer wants to publish an event to a topic called order-events.
The producer sends:
- Topic name
- Key
- Value
- Acknowledgement configuration (
acks=all)
Example:
{
"topic": "order-events",
"key": "user-42",
"value": {
"orderId": 1001,
"amount": 500
},
"acks": "all"
}Producer Needs Metadata First
A Kafka cluster contains multiple brokers.
The producer cannot randomly send data to any broker. It must determine:
- Which partition should receive the event
- Which broker is the leader for that partition
So the producer first requests metadata.
The metadata contains information like:
- Topic partitions
- Partition leaders
- Replica assignments
Example:
| Partition | Leader Broker |
|---|---|
| Partition 0 | Broker 1 |
| Partition 1 | Broker 2 |
| Partition 2 | Broker 3 |
If the broker receiving the metadata request does not have fresh metadata, it contacts the active controller.
Partition Selection
Kafka determines the partition using:
hash(key) % number_of_partitionsIf:
hash("user-42") % 3 = 1then the event belongs to:
Partition 1From metadata, the producer knows:
Partition 1 → Broker 2 is leaderSo the producer directly sends the event to Broker 2.
Broker Writes the Event
Broker 2 appends the event to the partition log.
Kafka logs are append-only.
Example:
Partition-1 Log
Offset 100 -> older event
Offset 101 -> new eventKafka never inserts in the middle.
It only appends at the end.
This is extremely important because append-only sequential writes are very fast on disk.
ISR and Acknowledgements
The producer used:
acks=allThat means the leader broker cannot immediately acknowledge success.
Instead:
- Leader writes the event
- Followers in ISR replicate the event
- Leader waits for ISR acknowledgement
- Only then does Kafka respond to the producer
Example ISR:
ISR = [Broker1, Broker2, Broker3]If Broker 2 is the leader:
- Broker 1 and Broker 3 must also replicate the event
- Then the producer receives success response
This provides stronger durability guarantees.
Complete Producer Flow
Consumer Read Flow
Consumers work differently from producers.
Kafka consumers are poll-based, not push-based.
Kafka never pushes data automatically.
Consumers continuously ask Kafka for new data.
Consumer Groups and Group Coordinators
Suppose a consumer joins a group:
notification-service-groupKafka must determine:
- Which broker will coordinate this group
- Which partitions this consumer should read
Kafka uses the internal topic:
__consumer_offsetsThis topic itself has partitions.
Example:
50 partitionsKafka calculates:
hash(groupId) % 50If:
hash(notification-service-group) % 50 = 23then:
Partition 23 of __consumer_offsetsmanages this consumer group.
Whichever broker is leader for Partition 23 becomes the:
Group CoordinatorConsumer Fetches Metadata
Just like producers, consumers also need cluster metadata.
The consumer requests:
- Topic information
- Partition leaders
- Coordinator information
The controller provides metadata if brokers do not already have fresh copies.
Joining the Consumer Group
The consumer contacts the group coordinator.
The coordinator:
- Registers the consumer
- Assigns partitions
- Stores consumer group metadata inside
__consumer_offsets
Example assignment:
Consumer-3 → Partition-2 of order-eventsThis information is replicated across ISR replicas of the coordinator partition.
Finding the Last Committed Offset
Suppose a previous consumer crashed. The new consumer must know where to resume reading. The consumer again contacts the group coordinator. The coordinator checks __consumer_offsets.
The lookup key looks conceptually like:
(groupId, topic, partition)Example:
(notification-service-group, order-events, partition-2)The stored value:
last_processed_offset = 101So the consumer resumes from offset 101.
Fetching Messages
Now the consumer directly contacts the leader broker for the assigned partition.
Example:
order-events → partition-2 → leader = Broker 2The consumer requests:
Fetch from offset 101
Return 200 bytesKafka returns records sequentially.
Example:
101
102
103
...The consumer processes the batch.
Offset Commit
After processing completes, the consumer commits offsets back to Kafka.
This commit is stored in:
__consumer_offsetsAgain, the consumer talks to the group coordinator.
Example commit:
Processed till offset 501Now if the consumer crashes later, Kafka knows where to resume.
Complete Consumer Registration & Fetch Flow
Kafka is Poll-Based
Kafka consumers continuously poll.
Flow:
Fetch batch
Process batch
Commit offset
Poll againExample:
Fetch from 502
Return next 200 bytesThis loop continues forever.
Log Retention and Cleanup
Kafka keeps appending events forever unless cleanup policies remove old data.
There are two major cleanup policies.
Delete Policy
Default policy:
cleanup.policy=deleteKafka deletes old segments based on Time and Size
Example:
retention.ms=7days
retention.bytes=1GBNote that retention works at the segment level, not per message. If a segment becomes older than retention time, delete the entire segment. If total partition size exceeds configured limit, delete oldest segments first.
Log Compaction
Compaction keeps only the latest value for a key.
Configuration:
cleanup.policy=compactExample log:
| Offset | Key | Value |
|---|---|---|
| 100 | user1 | v1 |
| 101 | user2 | v1 |
| 102 | user1 | v2 |
| 103 | user3 | v1 |
| 104 | user2 | v2 |
After compaction:
| Key | Latest Value |
|---|---|
| user1 | v2 |
| user2 | v2 |
| user3 | v1 |
Older values are eventually removed asynchronously.
Why Kafka is Fast
Kafka reads and writes from disk. Isn't disk slow? Kafka achieves very high throughput using several optimizations.
Write Optimization: Page Cache
Kafka does not synchronously write every request directly to disk. Instead, data first enters OS page cache (RAM). The OS asynchronously flushes to disk. This avoids blocking disk waits.
Sequential Writes
Kafka logs are append-only. So writes are always sequential. Sequential disk writes are dramatically faster than random writes.
Kafka never:
- updates records in place
- inserts in the middle
- modifies older events
It only appends.
Read Optimization: Zero Copy
Normally data flow looks like:
Disk → OS Page Cache → JVM/User Space → NetworkKafka optimizes this using the sendfile() system call.
With zero-copy:
Disk → OS Page Cache → NetworkKafka skips copying data into JVM user space.
Benefits:
- fewer memory copies
- lower CPU usage
- lower latency
- higher throughput