Leader Election via KRaft Controller Quorum in Kafka
How a small group of Kafka nodes votes for a boss, keeps the cluster's brain safe, and hands over the job in seconds when the boss disappears. Explained from zero, step by step, with everyday pictures and real-world examples.
Imagine a class of thirty students who need to plan a school trip. If everybody shouts ideas at the same time, nothing gets decided. So the class picks one student as the leader. The leader writes down the plan, and everyone else follows it. But what happens if the leader is sick on the big day? The class needs a fair and quick way to pick a new one, and it must never end up with two leaders giving two different plans.
Apache Kafka has exactly this problem, and it has it in a big way. A Kafka cluster is a group of computers that move huge streams of messages around. Somebody has to keep the master list of what topics exist, where every piece of data lives, and which computer is in charge of which piece. In modern Kafka, that job belongs to a small team called the KRaft controller quorum, and the team always has exactly one elected leader.
In this guide you will learn how that election works, why it is safe, what happens when things break, and how to run it well in production. We start with the very basics, so you do not need to know anything about Kafka, consensus, or distributed systems before you begin.
Why Leaders Matter: The Big Picture
Before any technical words, let us understand the simple problem that leader election solves.
A distributed system is a group of computers that work together so they look like one big computer. The group gives you more power and more safety, because if one computer breaks, the others can carry on. But there is a catch. When many computers share one job, they must agree on the facts. If computer A believes “the file lives on machine 7” and computer B believes “the file lives on machine 9”, users will get errors, lost data, or worse.
The easiest way to keep everyone in agreement is to have one computer make the decisions and tell the others. That computer is called the leader. The others are called followers. Followers copy what the leader decides and stand ready to take over. This pattern is used almost everywhere in big software systems, from databases to messaging systems to cloud control planes.
Think of a fire station with a captain. During an emergency, the captain gives orders and the firefighters follow them. If the captain is away, the station has a rule that says who becomes captain next. No one argues at the fire, because the rule was made before the fire started. Leader election is that rule, written for computers.
What is leader election?
Leader election is the process by which a group of computers chooses exactly one of them to be the leader. It runs when the group starts for the first time, and again whenever the current leader stops responding. The most important rule is that the group must never end up with two leaders at the same time. That dangerous situation has a name, split brain, and a good election design makes it impossible.
Two different elections in Kafka
Here is the part that confuses many beginners. Kafka actually has two layers of leaders. The first layer is the controller leader. It is one node, chosen by the KRaft controller quorum, that manages the whole cluster’s metadata. The second layer is the partition leader. Every slice of every topic has its own leader, and that leader is chosen by the controller leader. This guide focuses on the first layer, the KRaft election, and then shows how it powers the second layer.
Two layers, two jobs. The quorum elects the controller leader. The controller leader then elects partition leaders for the topics. If the top layer fails, the bottom layer cannot change until a new controller leader takes charge.
Why this matters to real businesses
Large companies run Kafka to move things like payment events, ride requests, video views, and sensor readings. When Kafka pauses even for a short time, apps that depend on it can stall. A fast and safe election means that the “brain” of Kafka recovers by itself, without a human waking up at three in the morning. That is why the election design is one of the most carefully engineered parts of the whole system.
Kafka Basics You Need First
A short tour of the Kafka words we will use again and again.
Kafka is a system for storing and moving streams of messages. Apps that send messages are called producers. Apps that read messages are called consumers. In the middle sits the Kafka cluster, made of computers called brokers. A broker is simply a server that stores messages on disk and serves them to consumers.
Topic
A named feed of messages, like a channel called “orders” or “payments”. Producers write to it and consumers read from it.
Partition
A topic is cut into partitions. Each partition is an ordered list of messages. More partitions means more work can run in parallel.
Replica
A copy of a partition kept on another broker. If one broker dies, a copy on another broker still has the data.
Partition Leader
The one replica that handles all reads and writes for a partition. The other replicas copy from it.
In-Sync Replicas (ISR)
The replicas that are fully caught up with the leader. Only these are trusted to become the next leader without losing data.
Controller
The special job of managing cluster metadata: topics, partitions, who leads what, and which brokers are alive.
Picture a huge library with many branches. Each book series is split into volumes (partitions). Every volume has a main copy at one branch (the partition leader) and spare copies at other branches (replicas). The head librarian’s office (the controller) keeps the master catalog that says which branch holds which main copy. When a branch closes, the head office announces which spare copy becomes the new main copy.
What is “metadata”?
Metadata means “data about data”. In Kafka it includes the list of topics, the number of partitions, which brokers hold each replica, who the current partition leaders are, access rules, and settings. It is small compared with the messages themselves, but it is extremely important. If the metadata is lost or confused, Kafka does not know where anything is, even though all the messages are still sitting on disk.
Why the metadata needs its own careful home
Many brokers must see the same metadata, and they must see changes in the same order. Suppose two admins create a topic with the same name at the same moment. Exactly one must win, and every broker must agree on which. Somewhere there must be a single trusted “source of truth” with a strict order of events. In Kafka, the KRaft controller quorum is that source of truth.
Kafka messages and Kafka metadata travel on different paths. Producers and consumers talk to the brokers about messages. Only the cluster’s own machinery talks to the controllers about metadata. So the controller quorum stays small and calm, even when message traffic is huge.
Life Before KRaft: The ZooKeeper Way
To appreciate the new design, we first look at the old one and the pain it caused.
For more than a decade after Kafka was born at LinkedIn, Kafka relied on a separate tool called Apache ZooKeeper. ZooKeeper is a small, well-known coordination service. It stores tiny pieces of data in a tree of nodes and lets many programs watch those pieces for changes. Kafka used it as its filing cabinet for metadata and as the referee for choosing a controller.
How the old election worked
In the ZooKeeper design, every broker was allowed to become the controller. All brokers raced to create a special short-lived entry in ZooKeeper. This entry could only exist once, so the first broker to create it won. The winner became the controller. If the controller died, its entry vanished automatically, ZooKeeper told the other brokers, and they raced again.
It is like a playground game with one special hat. Whoever grabs the hat first is the leader. When the leader goes home, the hat is left on the ground and everyone runs for it. It works, but it needs a neutral adult (ZooKeeper) to watch the hat and decide who really touched it first.
The pain points
Two systems to run
Teams had to install, secure, upgrade, monitor, and tune a second cluster next to Kafka, with different tools and different failure modes.
Slow controller failover
A new controller had to read the whole cluster’s metadata from ZooKeeper before it could work. With very many partitions, this could take a long time.
Partition ceiling
The amount of metadata that could be loaded and pushed to brokers limited how many partitions one cluster could safely hold.
Two sources of truth
The controller’s memory and ZooKeeper could disagree for a short time, which caused rare and confusing bugs.
Push instead of pull
In the old design, the controller pushed updates to every broker after each change. When a cluster had many brokers and many partitions, one change could trigger a flood of messages. Brokers that missed an update could hold a stale picture of the cluster until the next push. A better idea was for brokers to pull a shared log of changes at their own pace, which is exactly what KRaft does.
Meet KRaft: Kafka Raft in Plain Words
KRaft is Kafka’s own built-in way of agreeing on metadata, without any outside helper.
The community proposed the move away from ZooKeeper in a design document known as KIP-500 (a KIP is a “Kafka Improvement Proposal”). The plan was simple to say: let Kafka store its metadata inside Kafka itself, and let a small group of Kafka nodes agree on it using a well-known agreement method called Raft. The name KRaft is short for “Kafka Raft”.
The rollout happened in stages. KRaft first appeared as an early preview in the Kafka 2.8 line, became approved for production use in the 3.3 line, and ZooKeeper support was fully removed in the Kafka 4.0 line. Today, KRaft is the only way to run new Kafka clusters on current versions.
What is Raft?
Raft is a consensus algorithm. Consensus is a fancy word for “a group of computers agreeing on one answer, even when some of them crash or lose their network.” Raft was designed in the 2010s as an easier-to-understand alternative to older methods. It is now used inside many famous tools, such as etcd (the memory of Kubernetes), Consul, and CockroachDB.
Think of a group chat that plans a birthday party. One person, the organizer, decides what goes in the shared plan. Before an item is official, the organizer waits until more than half of the group replies “got it.” If the organizer goes silent, the group holds a quick vote for a new organizer, and the new one must have the latest version of the plan before winning.
The big idea: one log, many copies
KRaft keeps every cluster change in a single ordered list called a log. Every change, such as “create topic orders”, “broker 4 joined”, or “partition 2 now led by broker 5”, is added to the end of this log as a small record. The log lives in a special internal topic named __cluster_metadata, which has exactly one partition. Every controller keeps a copy of it, and every broker reads it too.
Because the log is ordered, everyone who reads it in order ends up with exactly the same picture. This is the heart of the whole design: the state of the cluster is simply the result of replaying the log. If you lose a node, you can rebuild its picture by replaying the log from the start, or from a saved snapshot plus the newer records.
KRaft uses Kafka’s own log idea for Kafka’s own metadata. The tool Kafka is famous for, an ordered and replicated log, is now also used to manage Kafka itself.
Why a leader is required
Raft allows only one node, the leader, to add records to the log. That single-writer rule guarantees that records have a clear order and never conflict. The other controllers are followers: they copy the leader’s log and wait. When the leader vanishes, they elect a new one from among themselves, and the new leader continues writing from exactly where the old one left off.
Node Roles and Deployment Modes
A Kafka process can wear one hat, or two. Let us see what each hat means.
Every Kafka server in KRaft mode has a setting called process.roles. It can say broker, controller, or both. This one setting decides what the server does in the cluster.
Broker role
Stores partitions, serves producers and consumers, and copies data between replicas. It never votes in the metadata election.
Controller role
Stores the metadata log and votes in elections. One of these becomes the active leader that makes all cluster decisions.
Combined mode
One process is both broker and controller. Handy for laptops, demos, and tiny test setups.
Dedicated (isolated) mode
Controllers run on their own machines, and brokers run on other machines. Recommended for serious workloads.
Why dedicated controllers are safer
Imagine the head librarian also had to carry boxes of books all day. If a huge delivery arrives, the librarian gets tired and slow, and the catalog stops being updated. In the same way, if a controller also serves heavy message traffic, a traffic spike or a slow disk can make the controller late for its own heartbeats. Late heartbeats look like a crash, and that triggers unnecessary elections. Keeping controllers on separate small machines protects the brain from the muscle.
| Question | Combined mode | Dedicated mode |
|---|---|---|
| Number of machines | Fewer | More |
| Risk of traffic slowing elections | Higher | Lower |
| Can scale brokers without touching voters | No | Yes |
| Best for | Learning and local tests | Production clusters |
Combined mode is not recommended for production. Growing your broker fleet in combined mode also grows your voter group, which is rarely what you want. Keep the voter group small and stable.
Voters and observers
Not every controller has to vote. In Raft, a node that copies the log but does not vote is often called an observer. Brokers act like observers of the metadata log: they read it, but they never vote for a leader and never count toward a majority. The nodes that do vote are the voters, and together they form the quorum.
Architecture and Components of a KRaft Cluster
Here is the whole picture: who talks to whom, and why.
flowchart TB
APP["Producers and Consumers"]
subgraph BF["Broker Fleet - data plane"]
B1["Broker 1"]
B2["Broker 2"]
B3["Broker 3"]
end
subgraph QU["KRaft Controller Quorum - control plane"]
C1["Controller 1 - ACTIVE LEADER"]
C2["Controller 2 - Follower"]
C3["Controller 3 - Follower"]
end
LOG[("Metadata Log - cluster_metadata topic")]
ADM["Admin Tools and Clients"]
APP -->|"send and read messages"| BF
ADM -->|"create topics and change settings"| C1
C2 -->|"fetch new records"| C1
C3 -->|"fetch new records"| C1
C1 -->|"appends records"| LOG
B1 -->|"register and heartbeat"| C1
B2 -->|"register and heartbeat"| C1
B3 -->|"register and heartbeat"| C1
B1 -.->|"fetch metadata"| C1
B2 -.->|"fetch metadata"| C1
B3 -.->|"fetch metadata"| C1
Let us walk through the figure from the top. Producers and consumers talk only to brokers. They never talk to controllers. Admin tools, such as the ones used to create topics, send their requests to the cluster, and those requests end up at the active controller, because only the active controller is allowed to change metadata.
The components, one by one
Active controller (the leader)
The single node that accepts every metadata change, puts it in order, and adds it to the log. It also decides partition leaders and watches broker health.
Standby controllers (the followers)
They fetch and store every record the leader writes. They apply the records to their own memory, so they are always “warm” and ready to take over quickly.
The metadata log
An append-only list of changes saved on each controller’s disk. It is the single source of truth. Old parts are compacted into snapshots so the log does not grow forever.
The quorum state file
A tiny file on each controller’s disk that remembers the latest leader, the current term number, and whom this node voted for. It survives restarts so a node cannot accidentally vote twice in the same term.
Brokers
They register with the active controller, send regular heartbeats, and keep pulling new metadata records so they always know the latest map of the cluster.
Think of a courtroom stenographer. The judge (active controller) speaks, and the stenographer writes every statement in strict order into one official record (the log). Other clerks (standby controllers) copy the record after each session. Reporters (brokers) read the official record instead of trusting rumors. If the judge falls ill, a clerk with the fullest copy of the record takes the bench.
Why the controllers keep things in memory
Every controller, not only the leader, builds a full picture of the cluster in memory by replaying the log. When a follower becomes the new leader, it already has that picture. It does not need to go off and load the whole cluster state from some outside place first. This is one of the biggest reasons why failover in KRaft is much faster than in the ZooKeeper design.
Raft Rules in Plain Words
Five simple ideas explain almost everything about how the election stays safe.
Idea 1: Terms, called epochs in Kafka
Time in Raft is chopped into numbered periods. Kafka calls each period an epoch. Each epoch has at most one leader. When a new election starts, the epoch number goes up by one. A bigger epoch always beats a smaller one. If a node ever sees a message with a bigger epoch than its own, it knows it is out of date and immediately steps back.
Epochs are like school years with a class monitor. In each year there is at most one monitor. If you come back from a long holiday and find out it is already the next year, you drop your old monitor badge, because the year that gave you the badge is over.
Idea 2: A majority decides everything
A candidate wins only if more than half of all voters say yes. With three voters, that means two. With five voters, that means three. Because two different majorities of the same group must overlap by at least one member, two candidates can never both win in the same epoch. This overlap trick is what makes split brain impossible.
Idea 3: One vote per epoch
A voter may give only one vote in each epoch, and it writes that vote to disk before replying. Even after a crash and restart, it remembers its vote and cannot vote for a second candidate in the same epoch.
Idea 4: Only well-informed candidates win
A voter refuses to vote for a candidate whose log is behind its own. It compares the epoch and position of the last record. This guarantees that any new leader already holds every record that the previous leader had told anyone was committed. So a committed change is never lost by an election.
Idea 5: Nodes are always in one of a few states
At any moment a controller is in one of a small set of states. The simplified picture below shows the main ones.
stateDiagram-v2
[*] --> Follower
Follower --> Candidate : leader silent too long
Candidate --> Leader : wins majority of votes
Candidate --> Follower : another leader appears or a higher epoch is seen
Candidate --> Candidate : split vote then retry with a new epoch
Leader --> Follower : sees a higher epoch or loses the majority
The real Kafka code has a few extra helper states, such as a node that has voted but has not yet heard from a leader, and a leader that is in the middle of gracefully resigning. They are refinements of the same simple picture.
How Kafka differs slightly from textbook Raft
In the original Raft paper, the leader pushes new entries to followers. KRaft flips this to match Kafka’s style: followers pull new records from the leader by sending fetch requests, just like Kafka replicas and consumers already do. Elections still use vote requests that candidates send out. This pull design reuses well-tested Kafka code and makes it easy for brokers, which are not voters, to follow the same log.
Because followers regularly fetch from the leader, those fetches double as heartbeats. If fetches stop arriving, the leader knows a follower is in trouble. If the leader stops answering fetches, the followers know the leader is in trouble.
Election Step by Step
Follow one full election from the moment the old leader disappears to the moment the new leader starts working.
Let us use a cluster with three controllers: Controller 1, Controller 2, and Controller 3. Controller 1 is the active leader in epoch 5. Everything is calm. Controllers 2 and 3 keep sending fetch requests to Controller 1, and Controller 1 keeps answering. Then, suddenly, Controller 1’s machine loses power.
sequenceDiagram
participant C1 as Controller 1 - old leader
participant C2 as Controller 2
participant C3 as Controller 3
Note over C1: Machine crashes in epoch 5
C2->>C1: Fetch request - no answer
C3->>C1: Fetch request - no answer
Note over C2: Fetch timeout expires and random wait ends
C2->>C2: Becomes Candidate in epoch 6 and votes for itself
C2->>C3: VoteRequest epoch 6 with last log position
C3-->>C2: VoteResponse granted
Note over C2: 2 of 3 votes so it becomes Leader
C2->>C3: Leader change record appended to the log
C3->>C2: Fetch request - gets the new record
Note over C2,C3: Cluster metadata writes resume
Silence is noticed
The followers keep a timer. Every successful fetch from the leader resets it. When no answer arrives for the whole timeout, a follower concludes the leader is gone. The default fetch timeout is about two seconds.
A small random pause
Before starting, the follower waits a short, randomly chosen time. This makes it unlikely that both followers jump in at exactly the same moment.
Becoming a candidate
The follower adds one to the epoch, moves into the candidate state, and records a vote for itself on disk. It now needs at least one more vote to reach a majority of three.
Asking for votes
The candidate sends a vote request to every other voter. The request carries the new epoch and the epoch and position of the candidate’s last log record, so voters can judge how fresh its copy is.
Voters check the rules
A voter says yes only if the epoch is new enough, it has not already voted in this epoch for someone else, and the candidate’s log is at least as up to date as its own. It saves the vote to disk first, then replies.
Counting and winning
Once the candidate holds a majority, it becomes the leader for that epoch. It appends a small record to the log announcing the change of leader, and followers begin fetching from it.
It is like a group of hikers whose guide suddenly falls silent on the radio. After a few seconds of waiting, one hiker announces “I will lead, who agrees?” The others agree only if this hiker has the most recent copy of the route map. Once most of the group says yes, the new guide steps forward and everyone follows the same route again.
The graceful path
Not every leadership change is a crash. If an operator shuts down the active controller on purpose, it can politely tell the other voters that it is stepping down. The followers then know the leader is leaving and can start the election right away instead of waiting for a timeout. Planned restarts, such as rolling upgrades, therefore cause even shorter pauses than crashes.
During a rolling upgrade of the controllers, upgrade the standby controllers first and the active one last. That way you cause only one leadership change instead of possibly several.
Split Votes, Timers, and Pre-Votes
What if two followers both decide to run at the same time? Kafka has a simple answer.
A split vote happens when two candidates start at nearly the same moment, and each collects its own vote but neither gets a majority. In a three-node group, if Controller 2 and Controller 3 both become candidates, each votes for itself, and each refuses the other. Nobody wins that round.
Raft’s answer is delightfully simple: randomness. Each candidate waits a random amount of time before trying again. Almost always, one candidate wakes up first, asks for votes first, and wins before the other even starts. The random wait is controlled by settings such as the election timeout and the maximum election backoff, and their defaults are on the order of one second.
Two friends reach for the same doorknob at the same instant and both say “you first!” and both freeze. The fix is not a rulebook. It is that each person waits a slightly different random moment before trying again. Very soon, one goes through and the problem is gone.
Why the timers must be tuned as a family
| Timer | What it controls | If set too low | If set too high |
|---|---|---|---|
| Fetch timeout | How long a follower waits for the leader before calling an election | Slow networks cause needless elections | Real crashes take longer to notice |
| Election timeout | How long a candidate waits for votes before trying again | Candidates give up before replies arrive | Split votes take longer to resolve |
| Election backoff | Upper limit for the random pause between attempts | More clashes between candidates | Slower recovery after a split |
| Request timeout | How long to wait for any single reply | Slow but healthy nodes look dead | Real failures are noticed late |
The “disruptive server” problem and pre-vote
Imagine one controller whose network cable is loose. It cannot hear the leader, so it keeps starting elections with bigger and bigger epoch numbers. When its network comes back, it announces a huge epoch, and the perfectly healthy leader is forced to step down because a bigger epoch always wins. The whole cluster suffers because of one flaky node.
To prevent this, newer Kafka releases added a pre-vote step. Before a follower raises its epoch, it first asks the others: “If I ran, would you vote for me?” Only if a majority says yes does it start a real election. A node that is cut off from everyone simply gets no positive answers and stays quiet, without pushing the epoch number up. Healthy leaders are no longer toppled by a lone troublemaker.
Repeated elections in your logs are almost never a “Kafka bug”. They usually point to slow disks, garbage-collection pauses, tiny CPU limits in containers, or a flaky network on a controller node. Fix the machine, not the timers.
After the Election: Epochs, Catch-Up, and the High Watermark
Winning the vote is only the first half. The new leader must also get the group back in sync.
The moment a candidate wins, it becomes the leader for the new epoch and adds one special record to the log. This record says “epoch 6 began, and I am the leader.” Followers replicate it like any other record. It also serves as a checkpoint: after this record is copied to a majority, the leader knows its authority is real.
Cleaning up the tail of the log
The old leader might have written some records that only it received before it crashed. Those records were never confirmed as committed. If a follower has such an extra tail, the new leader’s log wins. When that follower fetches, the leader tells it where the two logs first differ, and the follower throws away its extra records and copies the leader’s version. This is safe because uncommitted records were never promised to anyone.
The high watermark
The high watermark is a number that marks the last position in the log which is safely stored on a majority of voters. Records at or below it are committed, which means they will survive any future election. The leader raises the high watermark only after enough followers report that they have copied the records. Only committed records are shown to brokers and applied to the official cluster state.
Think of a teacher dictating homework. The teacher writes each line on the board, but the line only becomes “official” after most students confirm they have copied it. The high watermark is the last line on the board that most of the class has copied. If the teacher faints and a new teacher takes over, the class trusts every line up to that mark and simply re-checks anything past it.
Announce
The new leader appends its leader-change record so everyone learns the new epoch.
Reconcile
Followers with a divergent tail truncate it and copy the leader’s records instead.
Commit
Once a majority holds the new records, the high watermark moves forward.
Serve
The leader resumes accepting cluster changes: new topics, broker joins, leader moves.
Because all standby controllers already replayed the log into memory, the new leader does not have to rebuild the cluster’s state from scratch. The time between “old leader lost” and “new leader working” is mostly the failure-detection time plus a tiny voting round.
Why the Election Is Safe: Five Guarantees
Raft is trusted because it proves a small set of promises that always hold, no matter what crashes.
The people who designed Raft did not just test it. They wrote down a short list of properties that must always be true, and then showed why the rules make them true. KRaft inherits these properties. Understanding them in plain words will give you a deep feeling of trust in the whole system.
Election safety
At most one leader can be elected in any single epoch. This follows from the majority rule and the one-vote-per-epoch rule: two majorities always share at least one voter, and that voter only votes once.
Leader append-only
A leader never erases or rewrites its own records. It only adds new ones at the end. Only followers with a wrong tail ever remove records, and only uncommitted ones.
Log matching
If two logs have a record with the same position and the same epoch, then all the records before it are identical too. This lets a leader and a follower find quickly where their logs stop agreeing.
Leader completeness
Any record that was committed in an earlier epoch will be present in the log of every future leader. This is why voters refuse candidates with out-of-date logs.
State machine safety
If one node has applied a record at a certain position, no other node will ever apply a different record at that position. Everyone ends up with the same picture of the cluster.
Think of a school that keeps its official attendance register in three copies in three offices. Any change is only official when at least two offices have written it. When the register keeper is replaced, the school picks someone from the office that has the most complete copy. This guarantees that no confirmed line is ever lost and that all offices show the same history.
How old leaders are shut out
Every request between controllers carries the sender’s epoch. A node that receives a request with a lower epoch than its own simply rejects it and tells the sender about the newer epoch. So if an old leader wakes up after a long pause, such as a freeze caused by a garbage-collection stall, it will quickly learn it has been replaced and step down. This idea of using a growing number to lock out stale actors is often called fencing, and Kafka uses it in many places: controller epochs, partition leader epochs, and broker epochs.
These guarantees hold even if messages are delayed, lost, duplicated, or arrive out of order. They do not depend on perfect clocks. That is why Raft-based systems can be trusted on ordinary cloud networks where such things really do happen.
Replication, Commit, and Snapshots
How the metadata log stays identical on every controller, and how it stays small enough to manage.
The write path for one metadata change
A request arrives
An admin asks to create a topic. The request reaches the active controller.
Checks and planning
The leader validates the request: is the name free, are enough brokers alive, is the user allowed? It then works out the records that describe the change, such as the new topic and the placement of its partitions.
Append to the log
The records are added to the end of the leader’s log with the next positions in order.
Followers fetch
The standby controllers ask “anything new since position N?” and receive the new records. They store them on disk and report their progress on the next fetch.
Commit
When a majority holds the records, the high watermark advances. Only now does the leader answer the admin with “done.”
Everyone applies
Controllers and brokers, reading committed records, update their in-memory picture of the cluster.
Notice the pattern: the leader never tells the admin “success” until the change is safe on a majority. That is what makes it safe for the leader to crash right after answering. The change is already on at least two of the three machines, and any new leader must come from a group that includes at least one of them.
Why snapshots exist
A cluster can create millions of metadata records over years. Replaying all of them after every restart would be slow and would waste disk space. So each node periodically writes a snapshot, a compact copy of the entire cluster state at a certain log position. After a snapshot is safe, all older log segments can be deleted. On restart, a node loads the latest snapshot, then replays only the few records after it.
A bank does not replay every transaction since the day it opened to tell you your balance. It prints a monthly statement (the snapshot) and then only adds the latest few transactions on top. Kafka does the same thing with the cluster’s state.
Snapshots are taken automatically after a certain amount of new metadata or after some time has passed, whichever comes first. If a follower or a new broker has fallen so far behind that the leader has already deleted the records it needs, the leader simply sends the latest snapshot first and then the newer records. This is how a brand new controller or a broker that was offline for days catches up quickly.
Metadata disks should be fast and reliable, but they do not need to be big. The log is small compared with message data. What matters most is low and steady write latency, because every commit waits for a disk write on a majority of controllers.
What Lives Inside the Metadata Log
The log is just a long list of small records. Knowing the common ones makes the whole system feel less mysterious.
Every record in the metadata log is a tiny, typed message that describes one change to the cluster. Each type has a name and a clear purpose. When a controller or broker replays the log, it reads the records in order and updates its in-memory picture, one change at a time. Here are the most common kinds.
TopicRecord and PartitionRecord
Describe a new topic and where each of its partitions and replicas are placed. Deleting a topic adds a removal record.
PartitionChangeRecord
Says a partition’s leader, replica list, or in-sync list has changed. This is the record the active controller writes after a partition leader election.
RegisterBrokerRecord
Announces that a broker has joined, with its addresses and features. Other records track when a broker is fenced, unfenced, or removed.
ConfigRecord
Stores dynamic configuration changes for topics, brokers, and quotas so that every node agrees on them.
AccessControlEntryRecord
Holds access rules when the built-in authorizer is used. Permissions therefore travel with the same trusted log as everything else.
FeatureLevelRecord
Records the cluster’s feature levels, including the metadata version, which controls which record types the cluster may use.
Imagine the town council’s minute book. Each line is one decision: “a new school was approved,” “the bakery moved to Main Street,” “the mayor changed the parking rules.” Anyone who reads all the lines from the start knows exactly how the town looks today. The metadata log is that minute book for a Kafka cluster.
The metadata version
Kafka evolves, and new releases sometimes add new kinds of records. If a brand new controller wrote a record type that an older broker could not understand, the older broker would be confused. To prevent this, the cluster has a shared setting called the metadata version. It says “the cluster as a whole agrees to use record types up to this level.” During an upgrade, you first replace the software everywhere and only then raise the metadata version. Until you raise it, the cluster keeps writing records that old and new software both understand, which keeps rollbacks possible.
Why the log is a good design
Because every change is a record in an ordered list, several useful things come for free. A new broker can catch up by reading from a snapshot and then the tail. An auditor can see who changed what and in which order. A test can replay the log and check that it produces the same state. And because every node reads the same list, arguments about “who has the newest version of the truth” simply do not arise.
Raise the metadata version as a separate, deliberate step after an upgrade is fully finished and stable. Treat it like closing a door behind you: convenient, but not something to do during the middle of a rolling change.
How Brokers Follow the New Leader
Controllers elect a leader among themselves, but the brokers must also learn who it is.
Brokers are not voters, yet they depend on the active controller all the time. Each broker is configured with the addresses of the controller nodes. When a broker starts, it finds the current leader by asking. If it asks a follower, the follower answers with who the current leader is and which epoch it is in.
Registration and heartbeats
A broker first registers with the active controller, saying “I am broker 4, here are my addresses, and here are my supported features.” The controller writes this into the log. From then on, the broker sends a heartbeat every couple of seconds. The heartbeat carries the broker’s progress in reading the metadata log. The controller uses heartbeats to know which brokers are alive.
Think of a school roll call. Each student raises a hand every few minutes. If a hand does not go up for a long time, the teacher marks the student as absent and stops relying on that student for tasks. Brokers raising their hands are heartbeats, and the teacher is the active controller.
Fencing: keeping sick brokers out
If a broker’s heartbeats stop for longer than its session timeout (the default is about nine seconds), the controller fences it. A fenced broker is treated as unavailable: it loses any partition leadership it held, and it must catch up on metadata before it is allowed back in. This protects clients from talking to a broker that has lost touch with the cluster and might hold stale information.
Pull-based metadata updates
Brokers fetch new metadata records from the controller leader in the same way followers do, and apply them to their own in-memory view. When a new controller leader is elected, brokers’ fetches to the old leader start failing. They look for the new leader, reconnect, and continue from where they stopped. Because they pull from a position, they never miss an update, and they never apply one twice.
Controller pushes
Every change was pushed to every broker, so one change created lots of traffic and stale views if a push was missed.
Brokers pull
Brokers read a shared ordered log at their own speed and always know exactly where they are in it.
Producers and consumers usually do not notice a controller election at all. Messages flow through brokers and partition leaders, which stay in place. Only actions that need the controller, such as creating a topic or moving a partition leader, wait for a few seconds until the new leader is ready.
Partition Leader Election: The Second Layer
The controller leader’s most visible job is choosing who leads each partition.
Remember that every partition has one leader replica and some follower replicas. When a broker dies, all the partitions it led suddenly have no leader. Producers and consumers cannot use them until a new leader is picked. This is where the active controller earns its keep.
flowchart TD
A["Broker 2 stops sending heartbeats"] --> B["Active controller fences Broker 2"]
B --> C["Find every partition led by Broker 2"]
C --> D{"Is another In-Sync Replica alive?"}
D -->|"Yes"| E["Pick the first live replica from the In-Sync list"]
D -->|"No"| F{"Is unclean election allowed?"}
F -->|"No"| G["Partition stays offline until an In-Sync Replica returns"]
F -->|"Yes"| H["Pick any live replica and accept possible data loss"]
E --> I["Write partition change record to the metadata log"]
H --> I
I --> J["Majority of controllers commit the record"]
J --> K["Brokers fetch the record and update their roles"]
K --> L["Clients refresh metadata and use the new leader"]
The In-Sync Replica list is the safety net
A replica is in sync when it has copied everything the leader has, or is very close. By default, Kafka only lets an in-sync replica become the new leader. That way, the messages that were confirmed to producers survive the failover. When producers ask for the strongest guarantee, “acknowledge only after all in-sync replicas have the message,” a message that was confirmed is guaranteed to exist on whichever in-sync replica is picked next.
A relay race team has several runners who all watched the last handoff closely. If the current runner trips, the team picks a substitute from the ones who saw everything. Choosing a runner who arrived late and missed a handoff might save time, but the baton could be lost.
Who updates the In-Sync list?
The partition leader itself notices which followers are keeping up. When it wants to shrink or grow the list, it sends a request to the active controller. The controller checks the request against its records, including the leader’s epoch, and only then writes the change. This stops an old, confused leader from changing the list after a new leader has already taken over.
Unclean election: availability versus safety
If every in-sync replica is gone, Kafka has a hard choice. It can keep the partition offline and wait for one to return, which protects data but hurts availability. Or, if the setting for unclean leader election is on, it can promote an out-of-date replica. The partition comes back sooner, but some already-confirmed messages may be lost. The default is safety first: unclean election is off.
Preferred leaders and rebalancing
The first replica in a partition’s list is called the preferred leader. Kafka spreads preferred leaders evenly across brokers on purpose. After a failure, leadership may concentrate on a few brokers. A background task in the controller periodically checks the balance and, when the imbalance passes a threshold, moves leadership back to the preferred replicas.
| Type of election | Who decides | Triggered by | Data-loss risk |
|---|---|---|---|
| Controller leader election | Majority vote of the KRaft voters | Leader crash, resign, or long silence | None for committed metadata |
| Partition leader election | Active controller | Broker failure, shutdown, or rebalance | None from the In-Sync list, possible if unclean |
| Preferred leader election | Active controller | Timer or admin request | None |
Failure Scenarios and Recovery
A design is only as good as the way it behaves when things go wrong. Let us walk through the common failures.
Scenario 1: The active controller crashes
Followers miss the leader for about the fetch timeout, wait a short random time, one candidate wins a majority, and the new leader continues from the committed log. Typical cost: a few seconds during which no new metadata changes are accepted. Message traffic keeps flowing on existing partition leaders.
Scenario 2: One standby controller crashes
The leader still has a majority (two of three), so it continues to commit changes. When the standby returns, it fetches what it missed, or receives a snapshot if it was away for a long time. No election is needed.
Scenario 3: Two of three controllers are down
The quorum has lost its majority. The surviving controller cannot commit anything, so metadata changes stop. Existing partitions keep serving messages for as long as their leaders and replicas stay healthy, but new topics, leader changes, and broker joins are blocked until a second controller returns. This is a deliberate choice to prefer correctness over availability.
Scenario 4: A network split divides the controllers
Suppose the leader ends up alone on one side, with the two followers on the other. The two followers can form a majority and elect a new leader with a higher epoch. The old leader is in a minority, so it can never commit anything. In current releases, a leader that cannot hear from a majority for too long steps down by itself. When the network heals, the old leader sees the higher epoch and becomes a follower. There is never a moment with two working leaders.
Scenario 5: A slow disk on the leader
Writes stall, followers see delayed answers, and they may call an election. This is a good sign that the system notices trouble, but it also shows why controllers need steady, fast storage.
Scenario 6: A controller loses its data folder
A voter that comes back with an empty disk has also lost its memory of past votes. That is dangerous, because it could vote again in an epoch where it had already voted. Operators must treat such a node carefully, and should restore or re-add it through the documented procedure rather than just restarting it.
A committee with three members needs two to sign any document. If one member goes on holiday, signing continues. If two are away, nobody can sign anything, and the lone remaining member must wait. That feels annoying, but it means no forged or conflicting documents can ever exist.
Never “fix” a lost majority by forcing a lone controller to act as leader with a hand-edited setting. You might create two groups with different histories. Bring the missing controllers back, or follow the official recovery procedure for your Kafka version.
A Failure Timeline with Real Numbers
Let us put approximate times on a full failure so you can picture how long each phase takes.
The numbers below use typical default timers and are meant as a teaching picture, not a promise. Real clusters differ with network speed, machine load, and settings. The point is to see which phases dominate.
Case 1: The active controller machine loses power
| Approximate time | What happens |
|---|---|
| 0 seconds | The machine powers off. Fetch requests from followers start failing. |
| Up to about 2 seconds | The followers’ fetch timeout runs out. They decide the leader is gone. |
| About 0 to 1 second more | A small random wait, so that the two followers do not start at the same instant. |
| Tens of milliseconds | Vote requests and replies travel across a fast local network. |
| Right after | The winner becomes leader and appends the leader-change record. |
| Within a second or so | Brokers notice their fetches fail, find the new leader, and reconnect. |
Add these up and you get a total pause of a few seconds for tasks that need the controller. Notice that almost all of the time is spent noticing the failure and waiting the random pause, not in the vote itself.
Case 2: A broker machine loses power
| Approximate time | What happens |
|---|---|
| 0 seconds | The broker vanishes. Clients that were talking to its partitions get errors and start refreshing their maps. |
| Up to about 9 seconds | The controller waits for the broker’s session timeout, since heartbeats are missing. |
| Then | The controller fences the broker and picks new partition leaders from the in-sync lists. It writes the changes to the log. |
| A moment later | Other brokers fetch the new records and become leaders. Clients learn the new leaders and continue. |
In this case, the pause for the affected partitions is dominated by the broker session timeout. If the broker is shut down politely, it can tell the controller first, and leadership moves before the broker leaves, so clients often see almost no pause.
If a bus driver walks off the job unannounced, passengers wait until the depot notices the missing bus and sends a replacement. If the driver says “I am finishing my shift, here comes my replacement,” the passengers barely notice. Graceful shutdowns are the second kind.
Always stop brokers and controllers using the normal, graceful shutdown. Killing processes abruptly during maintenance forces the slower “wait for the timeout” path and creates avoidable pauses.
Sizing the Quorum: Three or Five Controllers?
How many voters should you run, and where should you put them?
The size of the quorum decides how many failures you can survive. The rule is simple: the group keeps working as long as a majority is alive. The table shows what that means for common sizes.
| Voters | Majority needed | Failures survived | Comment |
|---|---|---|---|
| 1 | 1 | 0 | Only for learning. Any failure stops the cluster’s brain. |
| 2 | 2 | 0 | Worse than one node, since two machines can fail instead of one. |
| 3 | 2 | 1 | The most common production choice. |
| 4 | 3 | 1 | No better than three, but costs more and adds more chatter. |
| 5 | 3 | 2 | For large or critical clusters that must survive a failure during maintenance. |
| 7 | 4 | 3 | Rare. Commits must wait for more machines, so writes get slower. |
Imagine a jury that needs more than half of its members to agree. A jury of three needs two. A jury of four needs three, so it can still lose only one member, exactly like a jury of three. Adding a fourth member adds cost but no extra safety. That is why odd numbers are the sensible choice.
Why not just add more voters?
Every commit has to wait for a majority to write to disk and reply. With more voters, the “slowest member of the fastest majority” tends to be slower, and there are more messages moving around. More voters also means more machines to secure and keep healthy. Most clusters do very well with three. Choose five when you want to keep full protection even while one controller is being upgraded or repaired.
Where to place the voters
Put each voter in a different failure zone. In a public cloud, that usually means different availability zones. With three voters in three zones, a whole zone can go dark and the quorum survives. Do not stretch the voters across faraway regions. Every commit would then pay the round-trip delay between regions, and long delays trigger false elections.
A good rule of thumb: three voters in three zones for most clusters, five voters in three zones (two, two, and one) for the most demanding ones. Keep the controllers on small, dedicated machines with fast local disks.
Changing the voter set later
Early KRaft releases used a fixed list of voters written in each node’s settings, and changing it needed careful, coordinated edits and restarts. Newer releases support a dynamic quorum, where an operator can add or remove a voter using a command while the cluster is running, and the change itself is recorded in the log. This makes replacing a broken controller machine much less risky.
Choosing the Right Setup for Your Situation
Different teams need different layouts. Here is a simple guide to picking one.
There is no single perfect layout. The right choice depends on how much a pause would cost you, how big your cluster is, and how many people you have to run it. Use the three situations below as starting points and adjust from there.
Learning, laptops, and small tests
Run one node in combined mode. It is quick to start and easy to throw away. Never keep anything important on it, because a single node has no protection against any failure. This is the right place to practice the commands, watch the logs, and read the quorum status for the first time.
A normal production cluster
Use three dedicated controllers in three separate zones, each with its own fast disk, and a set of brokers on separate machines. Turn on encryption and authentication for every listener, send logs and metrics to a central place, and set alerts for repeated leadership changes. This setup survives the loss of any single machine or any single zone.
A large, business-critical cluster
Use five dedicated controllers spread over three zones. This lets you take one controller down for maintenance and still survive an unexpected failure at the same time. Rehearse failovers regularly, keep a written runbook, and consider a second cluster in another region that receives copies of the data for disaster recovery.
| If your situation is | Then choose | Because |
|---|---|---|
| Just learning | One combined node | Simple and cheap, and nothing important is at stake |
| Production, moderate criticality | Three dedicated controllers in three zones | Survives one failure with the lowest cost |
| Production, high criticality | Five dedicated controllers in three zones | Survives two failures, including one during maintenance |
| Need to survive a whole region loss | A second cluster in another region with data copying | Keeps commits fast and still protects the business |
| Do not want to run controllers | A managed Kafka service | The provider handles the quorum, disks, and upgrades |
Start with the simplest layout that meets your needs today. Because the voter set can be changed later in newer releases, you are not locked in forever. It is better to be a little careful now than to build something huge that nobody understands.
Performance and Scalability
Why the small quorum can look after very large clusters.
It may seem odd that three little controller nodes can manage a cluster with dozens of brokers and a huge number of partitions. The reason is that metadata is tiny compared with message data. A partition needs only a few small records: where it lives, who leads it, and which replicas are in sync. Even with a very large number of partitions, the metadata fits comfortably in the memory of a controller.
What limits the speed of metadata changes?
Commit latency
Every committed change waits for a majority of controllers to write to disk. Faster, steadier disks mean faster changes.
Round-trip time
The leader must hear back from followers. A quiet local network keeps replies within a millisecond or two.
Single-writer processing
Only one thread on the leader orders changes. This keeps logic simple, and it is fast enough because each record is small.
Grouping changes
The leader can group many records into one disk write and one replication step. This turns a burst of changes into far fewer operations.
How the design scales
Adding brokers does not add voters. Brokers only read the log, so the quorum size stays fixed while the number of brokers grows. Reads scale easily because a broker fetches at its own pace and fetching is cheap. In the old push design, the controller had to send an update to every broker after each change, so its work grew with the size of the cluster. In KRaft, the leader only serves fetch requests, which are simple and can be answered from data already in memory or in the operating system’s cache.
Imagine a newspaper. The old design was a courier who ran to every reader’s house after each headline. The new design is a printed paper on the stand: readers come and pick it up when they like, and the editor’s work does not grow when more people read.
Startup and recovery speed
When a node restarts, it loads its last snapshot and replays only the newer records, so it is ready quickly. A failover is fast because standbys are already up to date. The Kafka community has reported far shorter controller failover and shutdown times, especially for clusters with very many partitions, compared with the ZooKeeper design. Exact figures depend on hardware and configuration, so measure your own environment.
Where the real limits still live
Metadata is not the only limit. Each partition still costs brokers memory, file handles, and replication work. Very large partition counts also mean longer recovery of the data itself after a broker restart. KRaft removes the controller as the main bottleneck, but good planning of partition counts is still an important part of running Kafka well.
“KRaft supports more partitions” does not mean “use as many as you like.” Choose the number of partitions from your real throughput and parallelism needs, and leave room for growth without going wild.
Advantages, Disadvantages, and Trade-Offs
No design is perfect. Here is an honest look at what KRaft gives you and what it asks of you.
ZooKeeper design versus KRaft design
| Topic | ZooKeeper-based Kafka | KRaft-based Kafka |
|---|---|---|
| Where metadata lives | In ZooKeeper, with a copy in the controller’s memory | In an internal Kafka log on the controllers |
| How the controller is chosen | Brokers race to create a special entry in ZooKeeper | Controller voters hold a Raft vote |
| Who can be controller | Any broker | Only nodes with the controller role |
| How brokers get updates | The controller pushes them | Brokers pull from the metadata log |
| New controller startup | Loads state from ZooKeeper first | Already holds the state in memory |
| Systems to operate | Kafka plus ZooKeeper | Kafka only |
| Access rules stored | In ZooKeeper | In the metadata log |
Advantages
- One system to install, secure, monitor, and upgrade instead of two
- Faster recovery when the active controller changes, because standbys are already warm
- Room for far more partitions per cluster than the old design allowed
- One source of truth: the ordered metadata log
- Simple mental model: brokers pull, controllers vote
- Fewer network hops and fewer moving parts to break
Disadvantages
- Teams must learn new tools and new failure modes
- Controller storage and timing now matter directly for cluster health
- Losing a majority of voters halts metadata changes
- Older clusters need a careful migration, and it is a project, not a checkbox
- Some older tools and scripts that talked to ZooKeeper must be updated
Trade-offs to understand
Correctness over availability
Without a majority, KRaft refuses to change metadata. It is choosing to be safe rather than to guess. This matches the well-known CAP idea: during a network split, a system must choose between consistency and availability, and the metadata quorum chooses consistency.
Fast detection versus false alarms
Short timeouts find dead leaders sooner but can mistake a slow leader for a dead one. Long timeouts are calmer but slower to react.
Dedicated controllers cost money
Extra machines add cost, but they buy stability. Small teams may start combined and move to dedicated later.
Clean versus unclean elections
Unclean partition election gives faster recovery but risks losing confirmed messages. Most systems that care about data keep it off.
Security of the Controller Quorum
The controllers hold the keys to the whole cluster, so they deserve special protection.
Whoever controls the metadata log controls Kafka. They can create or delete topics, change who is allowed to read data, and decide which brokers are trusted. This is why the controller quorum should be treated like the vault of the building, not like a normal room.
Separate the network path
Controllers use their own listener, separate from the ones that clients use. Only brokers, other controllers, and admin hosts should be able to reach it. Firewalls and security groups should say so plainly.
Encrypt traffic
Use TLS on the controller listener so that votes, fetches, and metadata records cannot be read or altered on the wire.
Prove identity
Require every peer to authenticate, through certificates or a supported login mechanism. A stranger must not be able to pretend to be a voter and ask for votes.
Control who can do what
In KRaft mode, the built-in authorizer keeps its access rules inside the metadata log itself. Grant admin powers to as few people and programs as possible.
Protect the disks
The metadata log and the quorum state file should be readable only by the Kafka service account. Use encrypted volumes and protect backups the same way.
Think of a bank. Customers use the front counter (broker listeners). Managers use a locked back office (controller listener) that needs a badge and has cameras. You would never put the vault door on the street just because it is convenient.
A common mistake is leaving the controller listener open to the entire company network “for testing” and forgetting it. Anyone who can reach it and is not asked to prove identity might read or change cluster metadata.
A bonus of the new design
Since the old external coordination service is gone, there is one less system to secure, one less set of passwords and certificates, and one less network path to guard. Security teams often count that as a real gain.
Monitoring, Logging, and Metrics
What to watch so you notice trouble long before your users do.
You can think of monitoring as three questions: Is there a leader? Is it stable? Is everyone keeping up? Kafka exposes many measurements that answer each one. Names and details can vary a little between versions, so treat this list as a guide to the ideas.
| What to watch | Why it matters | Warning sign |
|---|---|---|
| Number of active controllers | There should be exactly one across the cluster | Zero for more than a few seconds, or anything other than one |
| Current leader and epoch | Shows who leads and how many elections have happened | Epoch climbing again and again |
| Election latency | How long each election took | Long or growing values |
| Commit latency | Time for a majority to store a record | Rising values suggest slow disks or network |
| Follower lag in the metadata log | How far behind each voter or broker is | A node that keeps falling behind |
| Broker heartbeat and fenced-broker count | Shows brokers that lost contact | Brokers flapping between fenced and active |
| Metadata error count | Failures while applying metadata records | Anything above zero |
| Disk latency and free space on controllers | Every commit needs a disk write | Spikes in write time or near-full disks |
Useful command-line checks
Kafka ships with a tool that describes the state of the metadata quorum. It reports the current leader, the epoch, the high watermark, each voter’s position in the log, and how far behind each one is. Running it after every maintenance step is a cheap and powerful habit. Comparing the positions across voters quickly reveals a node that is quietly falling behind.
Logs to read
Controller logs tell a story: “fetch timeout expired,” “became candidate,” “granted vote,” “became leader.” If you see this story repeat every few minutes, something is wrong with a machine or a network. Send controller logs to your central logging system, and set an alert on leadership changes that happen more often than your normal maintenance schedule explains.
Alert on the pattern, not on a single election. One election during a planned restart is normal and healthy. Three elections in ten minutes with no maintenance is a sign to investigate.
Troubleshooting Playbook
When something looks wrong, this table helps you go from symptom to likely cause to first check.
| Symptom | Likely cause | First thing to check |
|---|---|---|
| Leader changes every few minutes | Slow disk, long pauses in the process, or a flaky network on one controller | Disk write latency, garbage-collection pauses, packet loss between controllers |
| No active controller for a long time | Majority of voters down or unreachable | Which voters are running, firewall rules, and DNS names |
| A voter keeps lagging behind | Weak machine, slow disk, or a network limit | The lag column of the quorum description tool and disk health |
| Brokers keep getting fenced | Heartbeats delayed by overloaded brokers or by network issues to the controllers | Broker CPU and pause times and the route to the controller listener |
| Topic creation hangs | No leader, or the leader cannot commit | Quorum status and commit latency |
| Node will not start after a change | Cluster ID mismatch or wrong voter list | The identity files in the metadata folder and the voter settings |
| Partition offline | No in-sync replica is alive and unclean election is off | Which replicas exist, and bring one of the in-sync brokers back |
A calm method for any incident
Find the leader
Ask the quorum tool who the leader is and which epoch it is in. If nobody is, you have a quorum problem. If someone is, you have a different problem.
Check each voter
Are all voters up? Are they close in log position? Which one is the odd one out?
Look at the machines
Check disk latency, CPU limits, memory pressure, and pauses on the suspicious node before touching Kafka settings.
Read the logs in time order
Line up the controller logs from all voters by time. The story of who timed out first often points to the guilty machine.
Change one thing
Fix one suspect at a time and watch the epoch and lag afterward. Changing many things at once makes it impossible to know what helped.
Keep a short written runbook next to your dashboards with the exact commands and expected healthy outputs. In the middle of an incident, nobody remembers the details, and a checklist calms everyone down.
Deployment, Migration, and Cloud
How KRaft clusters are actually created, moved, and run in real environments.
Starting a fresh cluster
A new KRaft cluster begins by choosing a unique cluster ID, a random label shared by every node. Each node’s storage folder is then prepared using a formatting tool that writes this ID and the initial metadata files. On first start, the voters find each other, hold their first election, and the winner begins writing the log. After that, brokers register and the cluster is ready.
Moving an existing ZooKeeper cluster
Teams with old clusters can migrate without downtime. The process has clear phases: first upgrade to a version that supports migration, then add a new KRaft controller quorum next to the old setup. The new controllers copy the existing metadata from ZooKeeper. Then brokers are restarted one at a time so they talk to the new controllers. During a middle period, the new controllers keep writing changes to both places, which allows a rollback. Finally, once everyone is happy, the old coordination service is switched off for good.
Prepare
Upgrade the cluster to a release that supports migration, and make sure everything is healthy.
Add controllers
Start the new controller quorum in migration mode. It reads the cluster’s metadata from ZooKeeper.
Roll the brokers
Restart brokers one by one so they connect to the new controllers.
Take over
Move control to the new quorum and confirm everything is stable. Rollback is still possible at this stage.
Finish
Remove the migration settings, restart the controllers, and retire the old coordination service.
Running on virtual machines, containers, and managed services
On virtual machines, give each controller its own instance with a persistent disk and a fixed name. On Kubernetes, controllers usually run as stateful workloads with stable names and persistent volumes, because a controller must come back with its old disk and its old identity. Operators such as Strimzi support this pattern. Managed services, including Amazon MSK on newer Kafka versions and Confluent’s cloud offering, run the controller quorum for you, which removes most of the operational work, though the ideas in this guide still explain what you see.
Container CPU limits that are too tight, and volumes that are shared with other busy programs, are two of the most common reasons for surprise elections in container platforms. Give controllers steady resources and their own storage.
Best Practices, Patterns, and Common Mistakes
Habits that keep the quorum calm, and traps that keep waking people up at night.
Best practices
Dedicated controllers
Use separate machines for controllers in production and keep them small, quiet, and stable.
Odd voter counts
Choose three, or five when you need to survive two failures. Never choose an even number.
Spread across zones
Put each voter in a separate failure zone within the same region.
Fast, private disks
Use low-latency local or high-quality network disks that are not shared with heavy workloads.
One controller at a time
Restart or upgrade controllers one by one, checking quorum health after each step.
Rehearse failures
In a test environment, stop the active controller on purpose and watch the election. Teams that have seen it once stay calm when it happens for real.
Useful design patterns
Small, boring control plane
Keep the metadata layer small and separate from the data layer, so that message traffic spikes never disturb the cluster’s brain.
Single writer, many readers
Let one leader put changes in order and let everyone else read the same log. This pattern removes conflicts by design and appears in databases, message systems, and coordination tools.
Snapshot plus tail
Store a compact snapshot of the state and only the newest records after it. Restarts and new members become quick.
Anti-patterns to avoid
What people do
They run combined broker-and-controller nodes in a large production cluster to save on machines.
Why it hurts
A heavy traffic burst or a long pause on a busy broker can delay controller heartbeats. The cluster then holds needless elections at the worst possible time.
Better approach
Run three small dedicated controller nodes. The saving from combining is tiny next to the cost of one outage.
What people do
They stretch the voter group across distant regions to survive a whole-region loss.
Why it hurts
Every metadata commit must wait for replies across a long network path. Slow replies look like failures, and elections start for no reason.
Better approach
Keep the quorum within one region across several zones. For region-level safety, replicate data between separate clusters instead.
What people do
They wipe a controller’s data folder to “fix” a strange problem and simply restart it.
Why it hurts
The node forgets its past votes and its place in the log. This risks breaking the guarantees that keep elections safe.
Better approach
Follow the official replacement procedure for your version, so the node rejoins with a properly recorded identity.
Common mistakes in short
- Using an even number of voters and believing it adds safety
- Setting timeouts by copy-and-paste without measuring your own network and disks
- Ignoring repeated small elections until a big outage happens
- Leaving the controller listener open to too many hosts
- Upgrading all controllers at once
Real-World and Industry Examples
The same ideas show up in famous systems that millions of people use every day.
LinkedIn: the birthplace of Kafka
Kafka was created at LinkedIn to move activity events such as page views and messages between systems. LinkedIn runs one of the largest Kafka deployments in the world, so it felt the pain of metadata size and slow controller recovery early. That experience shaped the community’s push toward a built-in metadata log.
Confluent Cloud and other managed Kafka services
Companies that operate thousands of clusters for customers benefit the most from a single-system design. Confluent has spoken publicly about moving its cloud service to KRaft, and Amazon MSK offers KRaft-mode clusters on newer Kafka versions. For these providers, fewer moving parts and faster recovery mean fewer alarms and simpler operations.
Netflix and Uber: heavy Kafka users
Streaming and ride-hailing companies send enormous streams of events through Kafka, such as viewing signals and trip updates. A fast, self-healing control plane matters to them because a metadata pause can back up event pipelines. These companies show the kind of scale where every second of controller downtime counts.
etcd inside Kubernetes
The same Raft idea guards the state of Kubernetes. A small group of etcd nodes elects a leader, and every change to the cluster’s desired state is written to a replicated log. Operators are advised to run three or five nodes and to give them fast disks, just like KRaft controllers.
Consul and CockroachDB
Consul uses Raft for its service registry. CockroachDB uses Raft for each range of its data, so it runs many small elections at once. Both show that “vote for a leader, replicate a log, commit on a majority” is a proven recipe.
Details such as exact adoption dates and cluster sizes change over time. Check the current documentation and release notes of your Kafka version and your cloud provider before making decisions based on any of the examples above.
A Day in the Life of a Cluster: A Short Story
Everything you learned, told as one simple story.
Imagine a food-delivery company called QuickBite. Its Kafka cluster has three dedicated controllers, called Ctrl-A, Ctrl-B, and Ctrl-C, placed in three different availability zones, and nine brokers spread around them. Ctrl-A is the active leader in epoch 12. Every few seconds the brokers send heartbeats to Ctrl-A, and Ctrl-B and Ctrl-C keep fetching new records from it.
Morning: a new feature
A developer adds a topic for “courier location updates.” The request goes to Ctrl-A, which checks it, decides the partition placement, appends records, waits until Ctrl-B has copied them, and then answers “done.” Brokers fetch the records and start creating the partition folders.
Noon: the lunch rush
Message traffic explodes on the brokers. Because the controllers run on their own quiet machines, their heartbeats and fetches keep their steady rhythm. Nobody notices any change in the control plane.
Afternoon: a zone has trouble
The zone that hosts Ctrl-A loses power. Ctrl-B and Ctrl-C stop getting answers. After the fetch timeout and a tiny random pause, Ctrl-C asks for votes in epoch 13. Ctrl-B sees that Ctrl-C’s log is just as complete as its own and votes yes. Ctrl-C becomes the leader.
Then: broker failures are handled
Three brokers in the failed zone also disappear. Ctrl-C waits for their session timeouts, fences them, and gives the affected partitions to other in-sync replicas. It writes the changes, Ctrl-B commits them, and the remaining brokers start leading those partitions. Couriers’ phones reconnect and continue sending updates.
Evening: the zone returns
Power comes back. Ctrl-A restarts, reads its saved state, sees that epoch 13 exists, and becomes a follower. It fetches the records it missed and catches up. The brokers rejoin, are unfenced, and after a while the controller moves leadership back to each partition’s preferred replica to balance the load.
During this whole story, nobody logged in to fix anything by hand. The design turned a zone-wide failure into a few seconds of delay for control-plane changes. That is exactly the goal of a quorum with automatic leader election.
Glossary: Every Term in One Place
A quick reference you can return to whenever a word slips your mind.
| Term | Simple meaning |
|---|---|
| Broker | A Kafka server that stores messages and serves producers and consumers |
| Controller | A Kafka node that stores the metadata log and can vote in elections |
| Active controller | The one elected leader among the controllers that makes cluster decisions |
| Quorum | The group of voters whose majority decides everything |
| Voter | A controller that takes part in elections and counts toward a majority |
| Observer | A node that reads the log but does not vote, such as a broker |
| Raft | A well-known method that lets a group of computers agree on one ordered log |
| KRaft | Kafka’s built-in version of Raft for managing its own metadata |
| Metadata | Information about the cluster: topics, partitions, leaders, settings, and access rules |
| Metadata log | The ordered list of every change to the metadata |
| Record | One entry in the log describing one change |
| Epoch | A number that grows with each election and identifies a leader’s period in charge |
| Candidate | A controller that is asking for votes to become the leader |
| Follower | A controller that copies the leader’s log and waits |
| Majority | More than half of the voters |
| Split vote | An election round where nobody reaches a majority |
| Pre-vote | A trial question asked before a real election to avoid needless disruption |
| High watermark | The last log position that is safely stored on a majority |
| Committed | Safely stored on a majority and guaranteed to survive future elections |
| Snapshot | A compact copy of the full cluster state at one moment in the log |
| Heartbeat | A regular signal that says “I am alive and up to date” |
| Fencing | Locking out a node that is stale, silent, or has been replaced |
| Partition leader | The replica that handles reads and writes for one partition |
| In-sync replica | A copy that is fully caught up with the partition leader |
| Unclean election | Choosing an out-of-date replica as leader, trading data safety for availability |
| Preferred leader | The first replica in the list, used to keep leadership evenly spread |
| Split brain | The dangerous situation of two leaders working at once, which the design prevents |
| Combined mode | One process acting as both broker and controller |
| Metadata version | The agreed level of record types that the whole cluster may use |
Frequently Asked Questions
Quick answers to the questions that beginners ask most often.
Summary and Key Takeaways
The whole story in a few short lines.
Key Takeaways
- Two layers of leaders: the controller quorum elects one active controller, and that controller elects a leader for every partition.
- KRaft replaces ZooKeeper: cluster metadata lives in an ordered, replicated log inside Kafka, agreed on using the Raft method.
- Majority rules: a candidate needs more than half of the votes, one vote is allowed per epoch, and only up-to-date logs can win. This makes two leaders at once impossible.
- Fast failover: standby controllers already hold the full state in memory, so a new leader can start working within seconds.
- Brokers pull and heartbeat: they follow the metadata log, and the controller fences any broker that goes silent.
- Run it carefully: use three or five dedicated controllers in separate zones, on fast disks, with secure listeners and alerts on repeated elections.
- Safety over availability: without a majority, metadata changes stop on purpose, because a quiet cluster is safer than a confused one.