Kafka Internals: Partitions, Leaders, and the Commit Log
Kafka's throughput and ordering guarantees both derive from the same mechanism — partition-scoped, append-only commit logs with leader-follower ISR replication. Understanding this single design decision makes every Kafka configuration choice obvious: acks, min.insync.replicas, partition key design, log compaction, and cooperative rebalancing.
Distributed Messaging Systems
Kafka Internals: Partitions, Leaders, and the Commit Log
The senior engineer on call at 3 a.m. sees the alert: Kafka consumer lag on payments.processed has climbed to 4.2 million messages and is growing. They increase the consumer group from 6 instances to 12. Lag continues climbing. The reason is that the topic has 6 partitions. Adding more consumer instances beyond the partition count does nothing — the extras sit idle. Kafka's consumer model is not a thread pool; it is a partition assignment. Understanding why requires going one level deeper than the API.
A message is a fact about the world — and Kafka's design encodes one specific, deliberate answer to the question of where that fact lives and who may read it.
Series positioning: This is Part 3 of Distributed Messaging Systems. Part 2 established the queue vs log distinction and the offset model. This article goes below the offset to the physical storage and replication layer. The existing Kafka Deep Dive (Distributed Architecture series) covers the foundational commit log model — this article assumes that baseline and focuses on the KRaft controller, acks matrix, cooperative rebalancing, and log compaction. Part 4 is the parallel RabbitMQ deep-dive.
1. The Partition: Kafka's Unit of Everything
1.1 One Partition, One Append-Only File
Every Kafka topic is divided into N partitions. A partition is not an abstraction — it is a directory on the broker's filesystem containing sequential segment files:
Producers append to the active segment at the tail. Consumers read from any segment by offset lookup. The broker never modifies written data — the log is immutable. This is what makes Kafka fast: sequential disk writes use the OS page cache optimally, and sendfile(2) zero-copy transfers data directly from page cache to the network socket without copying through userspace.
Kafka's throughput comes from two OS mechanisms: sequential I/O (appending to one file end) and zero-copy (sendfile syscall bypasses userspace copy). If your Kafka brokers are slow, check whether the page cache is being evicted — brokers with insufficient RAM force disk reads on every consumer fetch.
1.2 Partition Key and Ordering Guarantees
Kafka guarantees ordering within a partition, not across partitions. The partition a message lands on is determined by its key:
Ordering is scoped to a partition key, not a topic. Two events for the same payment ID are guaranteed to be ordered. Two events for different payment IDs on different partitions are not ordered relative to each other — and cannot be made so without a single-partition topic (which eliminates parallelism).
| Partition Key Design | Ordering Scope | Parallelism |
|---|---|---|
| No key (null) | None — round-robin | Maximum (all partitions used) |
Entity ID (payment:P1) |
Per entity | High (events per entity ordered; entities parallel) |
| Tenant ID | Per tenant | Medium (all tenant events ordered) |
| Constant key | Total ordering | None (single partition = single consumer) |
2. Replication: ISR and the acks Matrix
2.1 Leader-Follower Replication
Each partition has one leader broker and N-1 follower brokers (N = replication factor). All producer writes go to the leader. Followers fetch from the leader continuously, maintaining an In-Sync Replica (ISR) list — the set of followers that are caught up within replica.lag.time.max.ms (default 30s).
2.2 The acks Matrix: Durability vs Latency
acks |
min.insync.replicas |
Durability | Latency impact |
|---|---|---|---|
0 |
N/A | None — message may be lost even if broker is healthy | Lowest (+0ms) |
1 |
N/A | Leader-only — lost if leader crashes before replication | Low (+1–5ms) |
all |
1 |
Equivalent to acks=1 — ISR of 1 means only leader |
Medium |
all |
2 |
Safe under single broker failure | Medium (+5–15ms) |
all |
3 |
Safe under two concurrent broker failures | Higher (+15–30ms) |
acks=all without setting min.insync.replicas=2 provides false safety. If the ISR shrinks to 1 (followers fall behind), acks=all only requires the leader to confirm — identical to acks=1. Always set both together: acks=all + min.insync.replicas=2.
3. Consumer Groups and the Partition Assignment Problem
3.1 Why Max Parallelism = Partition Count
A partition can be assigned to at most one consumer within a group at any time. Six partitions, six consumers maximum. The seventh sits idle — this is why scaling consumer instances beyond partition count does nothing for throughput.
If consumer lag is growing and you're already at the partition count ceiling: (1) increase the partition count on the topic, (2) scale consumers to match. Partition counts can be increased but never decreased — plan ahead. A common production setting is 12–48 partitions for high-throughput topics to give future scaling headroom.
3.2 Cooperative Rebalancing vs Eager Rebalancing
When a consumer joins or leaves a group, Kafka must reassign partitions — this is a rebalance. The legacy eager (stop-the-world) protocol revokes all partition assignments, pauses all consumers, then re-assigns. For a group of 20 consumers this can cause 10–30 seconds of processing pause.
The cooperative (incremental) rebalancing protocol, available since Kafka 2.4 with CooperativeStickyAssignor, only revokes partitions that need to move:
| Protocol | Partition revocation | Pause during rebalance | Use case |
|---|---|---|---|
| Eager (default pre-2.4) | All partitions revoked | All consumers pause | Simple; safe with any assignor |
| Cooperative (incremental) | Only moved partitions revoked | Unaffected partitions continue | Production; reduces downtime |
4. KRaft: Kafka Without ZooKeeper
Since Kafka 3.3, the KRaft (Kafka Raft Metadata) mode replaces ZooKeeper as the controller. Understanding KRaft matters for cluster operations and failure recovery.
4.1 What Changed
| ZooKeeper mode (pre-3.3) | KRaft mode (3.3+) | |
|---|---|---|
| Metadata store | External ZooKeeper ensemble | Built-in Raft log on controller nodes |
| Controller election | ZooKeeper leader election | Raft consensus among controller quorum |
| Partition count limit | ~200K (ZooKeeper write bottleneck) | Millions (Raft log throughput) |
| Operational complexity | Two systems to operate | Single system |
| Startup time | Slow (ZooKeeper metadata load) | Fast (local Raft log replay) |
ZooKeeper mode is fully deprecated as of Kafka 4.0. If you are deploying new clusters, use KRaft. If you are operating existing ZooKeeper clusters, the migration path is a rolling metadata migration using kafka-storage.sh — it does not require downtime on brokers.
5. Log Compaction: Keeping the Latest Fact Per Key
For topics where only the latest value per key matters (user profile, product inventory, account balance), Kafka's log compaction removes superseded records, keeping only the most recent message per key:
Log compaction is the correct pattern for building event-sourced read models (KTable in Kafka Streams, or any consumer that bootstraps by replaying the compacted log). Do not use time-based retention for topics that serve as the source of truth for a read model — compaction ensures new consumers always get the complete current state without reading years of history.
Summary
| Concept | Rule |
|---|---|
| Partition as storage unit | Every partition is a single append-only file segment on disk; Kafka's throughput comes from sequential I/O and zero-copy OS transfers. |
acks durability |
acks=all + min.insync.replicas=2 is the only configuration that prevents data loss under a single broker failure. |
| Partition key ordering | Partition key determines ordering scope: all events with the same key are guaranteed to land on the same partition in the same order. |
What's Next
Part 4: RabbitMQ & AMQP — Smart Routing, Dead Letters, and Quorum Queues is the parallel deep-dive on the queue model: exchange types, binding topologies, quorum queue durability, channel multiplexing, and the dead-letter pipeline. If you arrived from Part 2 as a Kafka-focused reader, Part 4 is optional — the series converges at Part 5 on delivery guarantees, which you can read directly.
This article was developed with AI-assisted deep search, specification cross-referencing, and technical research synthesis.