Unclean Leader Election in Kafka

Unclean Leader Election in Kafka

What it is, why Kafka even allows it, how it can quietly erase messages that were already confirmed, and how to decide whether your cluster should ever switch it on.

Picture a busy online shop on a big sale night. Orders, payments and stock updates flow through Apache Kafka, and everything looks healthy. Then a server loses power. A minute later, the server that was supposed to take over also has a problem. Suddenly Kafka faces a hard question: should it stop and wait until a trusted copy of the data comes back, or should it carry on using a copy that might be missing the last few messages?

That question has a name, and the name is unclean leader election. It is one of the most misunderstood settings in Kafka. Some engineers think it is a harmless speed-up. Others think it is a bug switch that should never be touched. The truth sits in between, and this guide walks you through it slowly. We start from the very basics of how Kafka stores data, build up to how copies stay in sync, and then look closely at what really happens on the day a leader disappears. By the end you will know how to explain the topic in a design review, how to watch for it in production, and how to choose the right setting for each kind of data.

1What Is Unclean Leader Election?

Start with the plain-English idea. The technical details come in the next chapters.

Apache Kafka keeps several copies of every piece of data. One copy is the boss, called the leader. The other copies are helpers, called followers. All new messages go to the leader first, and the followers copy them from the leader. When the leader disappears because its machine crashed, lost power or lost its network, Kafka must quickly pick a new leader from the followers. Choosing the new leader is called a leader election.

Most of the time Kafka is picky. It only promotes a follower that is fully caught up with the leader. That is a clean leader election, because the new leader is guaranteed to hold every message that was confirmed to the sender. An unclean leader election happens when Kafka has no caught-up follower left and is allowed to promote a follower that is behind. The word “unclean” is a warning label. The new leader’s copy is not clean, because it may be missing messages that Kafka had already promised were safe.

Everyday analogy

Imagine a class where the teacher dictates a lesson and three students copy it into their notebooks. Some students write fast and some write slowly. The teacher suddenly falls ill. Rule A says that only a student who copied every page may take over the class. Rule B says that anyone in the room may take over, even a student who missed the last two pages. Under Rule A the lesson may pause for a while until a good note-taker is found. Under Rule B the lesson continues at once, but the last two pages are now missing from everybody’s notes. And if the real teacher returns with those pages, she has to tear them out to match the new notes.

Rule A is a clean election. Rule B is an unclean election. Kafka lets you pick the rule with a single setting called unclean.leader.election.enable. When it is false, Kafka follows Rule A and simply keeps the partition offline until a trustworthy copy returns. When it is true, Kafka follows Rule B. The partition comes back fast, but some confirmed messages may be lost forever.

false
default value of the setting since Kafka 0.11 (2017)
3
typical number of copies of each partition in production
0
unclean elections you should expect on a healthy day

Where the name and the default come from

In the early years of Kafka the setting was switched on by default. The thinking at the time was that people used Kafka mainly to move logs and activity events, where staying up mattered more than keeping every single record. As Kafka grew into a system that carries payments, orders and financial events, that default became risky. Starting with version 0.11.0, released in 2017, the default flipped to false. Kafka now protects your data first and your uptime second, unless you tell it otherwise.

i
Remember this sentence

Unclean leader election trades data safety for uptime. Everything else in this guide explains when that trade is wise and when it is a mistake.

A common myth to clear up early

Many people believe that turning the setting on makes Kafka run unclean elections all the time. It does not. The setting is only a permission. Kafka will use that permission in one very narrow situation: the leader is gone and no caught-up follower is alive. On a healthy cluster with good replication, this situation may never happen, and the setting will sit unused. The danger is not in the permission itself. The danger is in what the permission allows on the worst day of the year.

2Kafka Basics You Need First

A quick tour of the moving parts. If you already know Kafka well, skim the cards and jump to the diagram.

Kafka is a system for moving streams of events between programs. An event is a small record that says something happened, such as “user 42 placed order 9001” or “sensor 7 reported 21 degrees”. Programs that create events are called producers. Programs that read events are called consumers. In the middle sits a group of servers called a cluster, and each server in it is a broker. Kafka was created at LinkedIn to carry activity data such as page views and clicks. It became an Apache project, and LinkedIn has publicly described its own clusters as handling trillions of messages per day.

Server

Broker

One Kafka server. It stores data on its disks and answers requests from producers and consumers. A cluster usually has three or more brokers.

Category

Topic

A named stream of events, like “orders” or “payments”. Think of it as a folder that holds one kind of event.

Slice

Partition

A topic is cut into partitions. Each partition is one ordered list of events. Partitions let many brokers share the work.

Position

Offset

The number that gives each event its place inside a partition: 0, 1, 2, 3 and so on. Offsets never change once written.

Writer

Producer

An application that sends events to a topic. It decides how many brokers must confirm a write before it counts as done.

Reader

Consumer

An application that reads events in order and remembers its offset, so it knows where to continue after a restart.

Team

Consumer group

A team of consumers that share the partitions of a topic, so each event is handled by one member of the team.

Manager

Controller

One special broker role that watches the cluster and decides which copy of each partition is the leader.

The partition is an append-only log

Inside a broker, a partition is stored as a log: a file that only grows at the end. New events are added at the tail. Old events are never edited. This simple design is the secret of Kafka’s speed. Writing to the end of a file is very fast on ordinary disks, and reading a range of events in order is fast too. Old data is removed later by a retention rule, for example “keep seven days” or “keep 500 gigabytes”, or compacted so that only the latest value for each key remains.

Ordering is guaranteed inside one partition, but not across partitions. If two events must stay in order, they must go to the same partition. Producers usually achieve this by attaching a key, such as the customer ID, so that every event for the same customer lands in the same partition.

Everyday analogy

A partition is like a receipt roll in a shop’s till. Each new sale is printed at the end of the roll, and printed lines are never changed. A topic is a set of several tills working side by side, so that a long queue can be served faster. The offset is simply the line number on the roll.

flowchart LR
  P1["Producer App A"] --> B1
  P2["Producer App B"] --> B1
  subgraph CL["Kafka Cluster"]
    B1["Broker 1
Leader of Partition 0"] B2["Broker 2
Follower of Partition 0"] B3["Broker 3
Follower of Partition 0"] CT["Controller
decides who leads"] B1 -->|"replicates"| B2 B1 -->|"replicates"| B3 CT -.->|"assigns roles"| B1 CT -.->|"assigns roles"| B2 CT -.->|"assigns roles"| B3 end B1 --> C1["Consumer Group X"] B1 --> C2["Consumer Group Y"]
Figure 1. One partition with three copies. Producers and consumers talk to the leader. Followers copy from the leader. The controller assigns the roles.

Figure 1 shows a single partition, but a real topic has many partitions, and each partition has its own leader. Broker 1 may lead Partition 0 while Broker 2 leads Partition 1. This spreads the load. It also means that when one broker dies, only the partitions it was leading need new leaders. The other partitions keep running without a pause. Kafka clients do not need a load balancer in front of the brokers. They ask any broker for the cluster map, learn which broker leads which partition, and send each request straight to the right leader.

3Replication: Leaders, Followers and Copies

Machines fail. Kafka’s answer is to keep more than one copy of every partition.

If a partition lived on just one broker, that broker’s death would take the partition down with it, and if its disk broke, the data would be gone. Big clusters make this worse. With hundreds of brokers, hardware failures stop being rare surprises and become a normal weekly event. So Kafka keeps several copies of each partition on different brokers. Each copy is called a replica. The number of copies is the replication factor. A replication factor of 3 means every partition exists on three brokers. Most production clusters choose 3, because it survives the loss of one broker with room to spare.

One leader, several followers

Among the replicas of a partition, exactly one is the leader. Producers write only to the leader. Consumers normally read from the leader too. The remaining replicas are followers. A follower does not talk to producers at all. Its only job is to copy. It sends the leader a fetch request that says, “Please send me everything after offset N”, and appends whatever comes back to its own log, in the same order. This pull-based design is the same mechanism consumers use, which keeps the system simple.

Why only one leader? Because one writer per partition makes ordering easy. If two brokers accepted writes for the same partition at the same time, they would have to argue about which event comes first. Kafka avoids that argument by giving the pen to a single broker at a time.

Everyday analogy

Think of a shared diary with three photocopies. One friend, the leader, writes every new entry in the master diary. The other two friends visit every few moments, read the new lines, and copy them into their own diaries. If the friend with the master diary disappears, one of the other two must become the new writer. Whoever takes over must have a diary that is as complete as possible, or entries will be missing from the story.

Where the replicas live

Kafka spreads replicas across brokers so that no two copies of the same partition share a machine. Good clusters go one step further and tell Kafka which rack or cloud availability zone each broker sits in, using the broker.rack setting. Kafka then tries to place the copies in different racks or zones, so that one power failure or one zone outage cannot take out every copy at once. Here is a small example for a topic with three partitions and a replication factor of 3 on three brokers.

PartitionAssigned replicas (in order)Current leaderFollowers
Partition 0Broker 1, Broker 2, Broker 3Broker 1Broker 2, Broker 3
Partition 1Broker 2, Broker 3, Broker 1Broker 2Broker 3, Broker 1
Partition 2Broker 3, Broker 1, Broker 2Broker 3Broker 1, Broker 2

Notice two things. First, each broker leads one partition and follows two, so the work is shared fairly. Second, the order of the assigned replicas matters. The first replica in the list is called the preferred leader. Kafka tries to move leadership back to it when things are calm, so that the load stays balanced. The same order is also used as the queue of candidates when a new leader is needed. You will see why that detail matters in the chapters ahead.

!
Replication is not a backup

Replicas protect you from a machine dying. They do not protect you from a wrong deletion, a bad application that writes garbage, or a whole-region disaster. Copies are updated within moments, so a mistake spreads to all of them. Treat replication as protection against hardware failure only.

4The ISR: The Club of Caught-Up Copies

This is the most important idea for understanding unclean elections. Read it slowly.

Not every follower keeps up. A follower might sit on a slow disk, pause for a long garbage-collection cycle, lose its network for a while, or simply be restarting. Kafka needs to know which followers are close enough to the leader to be trusted. So the leader keeps a list called the ISR, which stands for in-sync replicas. The ISR always includes the leader itself, plus every follower that has been keeping up.

What does “keeping up” mean? Kafka uses time, not a count of messages. A follower stays in the ISR as long as it has caught up to the end of the leader’s log at least once within the last replica.lag.time.max.ms milliseconds. In recent Kafka versions, the default for this setting is 30 seconds. If a follower has not fully caught up within that window, the leader removes it from the ISR. When the follower catches up again, the leader lets it back in. So the ISR shrinks and grows as conditions change.

Everyday analogy

The ISR is like a book club where members must have finished the latest chapter. If a member falls more than a certain time behind, they are moved to the waiting list. They can rejoin as soon as they finish the reading. When the club needs a new discussion leader, it is safest to pick from the members who have read everything.

How a follower drops out of the ISR

1

The follower slows down

A long pause, a busy disk or a network problem makes its fetch requests late. It falls behind the leader’s newest message.

2

The leader watches the clock

The leader tracks when each follower last reached the end of the log. The follower’s “last caught up” time gets older and older.

3

The time limit is crossed

Once that time is older than the allowed lag, the leader decides the follower is no longer in sync.

4

The ISR shrinks

The leader asks the controller to record a smaller ISR. From now on, this follower is not counted when Kafka decides that a message is safely stored.

5

The follower catches up and returns

When the follower reaches the leader’s log end again, the ISR expands and the follower is trusted once more.

Why the ISR is a promise

The ISR is not just a status list. It is the promise that makes Kafka’s safety rules work. A message counts as committed only after every replica currently in the ISR has stored it. So if a message is committed, then every member of the ISR has it. That means any ISR member can safely become the next leader without losing a committed message. This is the core reason why clean elections choose only from the ISR.

Now look at the danger hidden in this design. The ISR can shrink all the way down to just the leader. If two followers are slow or down, the ISR is the leader alone. At that moment, messages are being committed by a group of one, and your “three copies” have quietly become a single copy. The cluster still looks healthy from the outside. Producers still get their confirmations. But if that lone leader dies now, there is no in-sync copy left anywhere.

!
Common cause of shrinking ISRs

Long garbage-collection pauses in the broker process, overloaded disks, network congestion between brokers, brokers that are restarting one after another too fast, and traffic spikes that the followers cannot keep up with. Watching how often the ISR shrinks is one of the best early warnings you can have.

5High Watermark, Log End Offset and “Committed”

Three small terms that decide which messages are safe and which are only “probably fine”.

Every replica has a log end offset, shortened to LEO. This is simply the offset of the next message the replica will write, so it tells you how far that copy has grown. If a replica holds offsets 0 through 9, its LEO is 10. The leader also keeps a number called the high watermark, shortened to HW. The high watermark is the smallest LEO among all replicas in the ISR. Every message with an offset below the high watermark is committed, meaning all in-sync copies hold it.

BrokerRoleHolds offsetsLEOIn ISR?
Broker 1Leader0 to 910Yes
Broker 2Follower0 to 78Yes
Broker 3Follower0 to 89Yes

In this example the smallest LEO among the three in-sync replicas is 8, so the high watermark is 8. Offsets 0 to 7 are committed. Offsets 8 and 9 exist on the leader, but they are not committed yet, because Broker 2 has not copied them. Consumers are only allowed to read below the high watermark, so they see offsets 0 to 7 and nothing more. This rule stops consumers from reading a message that might vanish if the leader crashed a moment later.

flowchart LR
  L["Broker 1 - Leader
holds offsets 0 to 9
LEO = 10"] F1["Broker 2 - Follower
holds offsets 0 to 7
LEO = 8"] F2["Broker 3 - Follower
holds offsets 0 to 8
LEO = 9"] HW["High Watermark = 8
offsets 0 to 7 are committed
consumers read only these"] L --> HW F1 --> HW F2 --> HW
Figure 2. The high watermark is the lowest LEO in the ISR. Only messages below it are committed and visible to consumers.
Everyday analogy

Think of a courier who delivers a package to three offices. The package is only marked “delivered and signed for” once the slowest office has signed. The high watermark is the line of packages that all offices have signed for. Anything beyond that line is still on the truck.

What the producer is told: acks and min.insync.replicas

The producer chooses how much certainty it wants before it treats a write as done. This choice is called acks.

SettingThe producer waits forRisk if the leader dies right after
acks=0Nothing at all. It fires and forgets.The message can be lost without anyone noticing.
acks=1The leader alone to write it.The message is lost if followers have not copied it yet.
acks=allEvery replica in the ISR to write it.Safe, as long as the ISR still has at least one member left.

A second setting, min.insync.replicas, sets a floor for acks=all. With a replication factor of 3 and min.insync.replicas=2, the leader refuses to accept a write unless at least two replicas, itself included, are in the ISR. If the ISR shrinks to one, producers get an error instead of a false sense of safety. Recent Kafka clients use acks=all by default, and that is the setting you want for data you care about.

!
A subtle trap in the word “all”

With acks=all, “all” means all replicas in the ISR, not all replicas that exist. If the ISR has shrunk to one and min.insync.replicas is set to 1, then acks=all means only the leader has to write the message. The producer gets a confirmation, but the data lives on a single machine. This is exactly the situation in which an unclean election does its damage.

6Internal Working: The Life of a Write and a Failover

Before we study elections, let us watch one message travel through the cluster. The election rules make much more sense afterwards.

Most explanations of Kafka skip the small steps in the middle, but those steps are exactly where the safety promises are made. When you know who does what, and in which order, the phrase “committed message” stops being abstract. It becomes a picture you can draw on a whiteboard. Follow the journey of a single write below.

The life of one write

1

The producer batches records

It collects records for the same partition into a small bundle, called a batch. It may wait a few milliseconds to fill the batch and may compress it to save network and disk.

2

The producer finds the leader

It uses its cached map of the cluster to learn which broker leads the target partition, and sends the batch straight there.

3

The leader checks the request

It confirms that it still leads the partition and that the epoch in the request is not stale. For acks=all it also confirms that the ISR is at least as large as min.insync.replicas. If any check fails, the request is refused with an error.

4

The leader appends to its log

It assigns the next offsets and writes the batch to the end of the log. The data lands in the operating system’s memory cache and is flushed to the physical disk in the background.

5

The followers fetch and copy

Each follower keeps a long-waiting fetch request open. As soon as new data appears, the leader answers, and the follower appends the records to its own log in the same order.

6

The leader moves the high watermark

Every time a follower asks for more, it tells the leader how far it has copied. When every ISR member has passed the new records, the leader raises the high watermark.

7

The producer gets its confirmation

The leader had parked the producer’s request in a waiting area. Once the high watermark passes the batch, it releases the request with a success reply. Consumers may now read those records.

sequenceDiagram
  autonumber
  participant P as Producer App
  participant L as Leader Broker
  participant F1 as Follower 1
  participant F2 as Follower 2
  P->>L: Produce request with acks=all
  Note over L: Check epoch and ISR size, then append at next offsets
  F1->>L: Fetch from my log end
  L-->>F1: New records
  F2->>L: Fetch from my log end
  L-->>F2: New records
  F1->>L: Next fetch shows the new log end
  F2->>L: Next fetch shows the new log end
  Note over L: All ISR members have the records, high watermark moves up
  L-->>P: Acknowledgement
  L-->>F1: High watermark in the next fetch reply
  L-->>F2: High watermark in the next fetch reply
Figure 3. The write path with acks=all. The confirmation is released only after every ISR member has copied the records.
!
Kafka’s durability comes from copies, not from constant disk syncing

By default, Kafka does not force every write onto the physical disk before answering. It relies on the fact that several brokers hold the data in memory or on disk at the same time. This is fast and works well when failures are independent. It also explains why putting all copies in one zone or one rack is risky: a single power event could take away every in-memory copy together.

How the controller knows a leader is gone

Each broker regularly tells the controller that it is alive. In ZooKeeper-based clusters this happened through a session that expired when heartbeats stopped. In KRaft clusters, brokers send heartbeats to the controller quorum, and the broker is fenced if they stop for longer than the session timeout, which is a matter of seconds by default. When the controller declares a broker gone, it walks through every partition that broker was leading and elects a new leader for each one, using the rules that the next chapters describe in detail.

The controller also guards the ISR. A leader cannot change its own ISR unilaterally. It sends a request to the controller that says, “I would like to shrink or grow the ISR to this set”. The controller checks the request against the current leader epoch and partition epoch, and only then records the change. This prevents an outdated leader from shrinking the ISR in a way that could hide data from the rest of the cluster.

Where the time goes in a failover

A failover has several phases, and each adds a little delay. First comes detection, because the controller must be sure that the broker is really gone and not just slow. Second comes the decision, when the controller picks a new leader for each affected partition. Third comes propagation, when the new leader and epoch are sent to all brokers. Finally, clients must notice that their old requests failed, refresh their cluster map and reconnect to the new leader. In a well-tuned cluster this takes a few seconds. In a cluster with tens of thousands of partitions on the failed broker, it may take noticeably longer, because each partition needs its own decision.

Production example: why detection time is a real trade-off

A platform team once shortened its broker session timeout to make failovers faster. The next time a broker paused for a long garbage-collection cycle, the controller declared it dead, moved many leaders away, and then the broker came back and had to catch up. The cluster paid the cost of a full failover for a problem that would have vanished by itself. The lesson: a very short timeout finds real failures sooner, but it also treats slow brokers as dead ones, which causes extra elections and ISR shrinks. Choose a value that matches your real pause behaviour.

7Clean Leader Election: The Safe Way

Before we study the risky path, let us see what Kafka does by default.

Leader elections are run by the controller. In older Kafka clusters the controller was one broker chosen with the help of ZooKeeper, a separate coordination service. In modern clusters that use KRaft mode, the controller role belongs to a small quorum of servers that keep the cluster’s metadata in their own replicated log. Kafka 4.0 and later run in KRaft mode only. The mechanics differ a little, but the rules for choosing a leader are the same in spirit.

The controller watches which brokers are alive. When it learns that a partition’s leader is gone, it walks through the partition’s list of assigned replicas in order and picks the first one that is both alive and in the ISR. It then bumps a counter called the leader epoch, records the new leader and the remaining ISR, and tells the other brokers about the change. Producers and consumers notice that their requests to the old leader fail, refresh their view of the cluster, and continue with the new leader. In a healthy cluster, this whole process takes a matter of moments.

1

The leader disappears

The broker crashes, is shut down, or loses contact with the controller. The controller notices missing heartbeats or a closed session.

2

The controller checks the ISR

It looks at the partition’s current ISR and asks which of those replicas are alive.

3

A live ISR member is promoted

The first live ISR replica in the assignment order becomes the new leader. The leader epoch goes up by one.

4

The cluster learns the news

Brokers receive the updated leader and ISR. Followers begin fetching from the new leader.

5

Clients reconnect

Producers and consumers refresh their cluster map and send their next requests to the new leader.

Why this path never loses committed data

Remember the promise from chapter 4: a message is committed only after every ISR member has it. The new leader is an ISR member, so it has every committed message. Nothing that was confirmed under acks=all can be missing. Some uncommitted messages, those that were on the old leader but not yet copied everywhere, may be lost, but the producer was never told those were safe. A well-written producer simply retries them.

Kafka has other clean ways to change leaders as well. During a planned shutdown of a broker, called a controlled shutdown, the controller moves leadership away in an orderly manner before the broker stops. A preferred leader election moves leadership back to the first replica in the list once it has caught up. Both choose only from the ISR, so both are safe. They are not the subject of this guide, but it helps to know they exist, because people sometimes confuse “leader election” with “unclean leader election”. Only one of them can lose data.

Production example: a payments ledger topic

A payments company keeps a “transactions” topic with a replication factor of 3, min.insync.replicas=2, and unclean election switched off. When one broker fails, an in-sync follower takes over in moments and no confirmed transaction is lost. When two brokers fail at the same time, the partition goes offline and payments for that slice of customers wait. The team accepts this delay, because a short outage is far cheaper than a ledger with missing entries.

i
The catch

Clean election has one weakness: it needs at least one live, in-sync replica. If every ISR member is down, the controller has no safe candidate. With unclean election disabled, the partition stays offline. Nobody can write to it and nobody can read from it until an in-sync replica comes back. This is the moment where the two rules part ways, and it is the subject of the next chapter.

8Unclean Leader Election: The Risky Way

What Kafka does when no safe candidate exists and the setting allows it to take a risk.

An unclean leader election happens when three conditions come together. First, the partition has no leader, because the old leader failed. Second, every replica that was in the ISR is dead or unreachable. Third, the setting unclean.leader.election.enable is true for that topic. When all three are true, the controller stops insisting on the ISR. It looks again at the full list of assigned replicas and picks the first one that is alive, even though that replica was outside the ISR and may be missing recent messages.

The controller then does one more thing that is easy to miss. It resets the ISR to contain only the new leader. The other replicas are no longer trusted, so they must prove themselves again by catching up. From this moment on, the new leader’s log is the official history of the partition. Whatever the old leader had beyond that point is no longer part of the story.

flowchart TD
  A["Leader of a partition fails"] --> B{"Is any ISR replica alive?"}
  B -->|"Yes"| C["Clean election
promote first live ISR replica
no committed data lost"] B -->|"No"| D{"Is unclean.leader.election.enable true?"} D -->|"No"| E["Partition stays OFFLINE
no reads and no writes
wait for an ISR replica to return"] D -->|"Yes"| F{"Is any other replica alive?"} F -->|"Yes"| G["Unclean election
promote first live replica
ISR becomes only the new leader
data loss is possible"] F -->|"No"| E
Figure 4. The decision the controller makes when a leader fails. Unclean election is only reached when no ISR replica survives and the setting is on.

Clean and unclean side by side

QuestionClean electionUnclean election
Who can become leader?Only live members of the ISRAny live replica, including ones outside the ISR
Can committed messages be lost?NoYes, if the chosen replica is behind
What if no candidate is alive?Partition offline until an ISR member returnsPartition comes back if any replica is alive
What is the new ISR?The surviving ISR membersOnly the new leader
Who notices a problem?Clients see a short pauseNobody, unless you monitor for it
Best suited forPayments, orders, ledgers, stateLogs, metrics, disposable events

Three ways the permission can be granted

The setting can be applied at the broker level, so that it becomes the default for all topics, or at the topic level, so that it overrides the default for one topic only. Kafka also allows these values to be changed while the cluster is running, without a restart. That flexibility is useful, because it lets you enable the permission only for the topics that truly need it. It is also dangerous, because a change made in a hurry during an incident can be forgotten and left in place for months.

Recent Kafka versions also provide a way to run an unclean election on demand. An administrator can use the kafka-leader-election tool, or the matching admin API, to ask for an unclean election on a partition that currently has no leader. This lets an operator make a deliberate, one-time decision during an outage without switching the topic to permanent “unclean” behavior. It is a much better habit than leaving the setting on “just in case”.

!
Not the same as preferred leader election

Preferred leader election moves leadership back to the first replica in the list, and only when that replica is in the ISR. It is a routine load-balancing step and is safe. Unclean election is an emergency measure that reaches outside the ISR. The names sound alike, but the risks are completely different.

9Step by Step: How Confirmed Messages Disappear

One concrete story, with real offsets, from the first slow follower to the final loss.

Numbers make the idea easier to hold, so let us follow one partition with a replication factor of 3. The assigned replicas are Broker 1, Broker 2 and Broker 3, in that order. Broker 1 is the leader. The producer uses acks=all, but the topic has min.insync.replicas=1, which is a common accidental setting. Unclean leader election is enabled on the topic.

1

Everything is healthy

All three brokers are in the ISR. Offsets 0 to 4 are stored on all three. The high watermark is 5.

2

Broker 3 falls behind

Broker 3 hits a long pause after offset 4. It stays stuck at a log end of 5. After the lag time limit passes, the leader removes it. The ISR is now Broker 1 and Broker 2.

3

Broker 2 crashes

Broker 2 has copied offsets up to 7 and then its machine reboots. The ISR shrinks to just Broker 1. Broker 2 is at a log end of 8, and Broker 3 is at 5.

4

Producers keep writing

Because min.insync.replicas is 1, Broker 1 accepts new messages on its own. Offsets 8 to 12 are written and confirmed. The high watermark moves to 13. Those five messages exist on Broker 1 only.

5

Broker 1 fails for good

Its disk fails or its machine is lost. There is no ISR member left. With unclean election off, the partition would be offline. With it on, the controller looks for any live replica.

6

Broker 2 returns and is promoted

Broker 2 comes back with a log end of 8. It is first in the list among live replicas, so it becomes the new leader. The leader epoch increases, and the ISR is reset to Broker 2 alone.

7

The new history begins

Producers write new messages. They receive offsets 8, 9, 10 and so on. The five confirmed messages from the old offsets 8 to 12 are gone from the cluster.

sequenceDiagram
  autonumber
  participant P as Producer App
  participant B1 as Broker 1 Leader
  participant B2 as Broker 2
  participant B3 as Broker 3
  participant C as Controller
  P->>B1: Send messages for offsets 8 to 12
  B1-->>P: Confirmed, ISR holds only Broker 1
  Note over B1: Offsets 8 to 12 exist only here
  Note over B1: Broker 1 fails permanently
  C->>C: No ISR replica is alive
  C->>B2: Unclean election, become leader with epoch 1
  Note over B2: Log end is 8, five messages are missing
  B2-->>C: Leader ready, ISR is only Broker 2
  P->>B2: Send new messages
  B2-->>P: Confirmed, they receive offsets 8 and up
  B3->>B2: Fetch from offset 5
Figure 5. The order of events in an unclean election. The confirmed messages at offsets 8 to 12 were only ever on Broker 1.
5
confirmed messages lost in this story (offsets 8 to 12)
0
errors shown to the producer that sent them
1
setting change away from a partition that stays offline

The two ingredients that made this possible

Look closely at what had to go wrong. The story needed both a shrunken ISR that let a single machine confirm writes, and the permission to elect an out-of-sync replica. If min.insync.replicas had been 2, Broker 1 would have rejected the writes for offsets 8 to 12 after the ISR fell to one, and no message would have been confirmed with a single copy. If unclean election had been disabled, the partition would have gone offline at step 5 and waited for Broker 2 to be recognized as the last trusted copy. The loss needs both weaknesses together, which is why each defence matters.

i
The quiet part

Nothing in this story raises an error for the producer or the consumer at the moment of loss. The producer received its confirmations at step 4, and they were honest at that time. The damage appears later, as missing records. This is why unclean elections are hard to notice without proper monitoring.

10Where the Data Goes: Log Truncation and Leader Epochs

What happens when the old leader comes back and its diary no longer matches the new one.

Suppose Broker 1 in our story is repaired and restarted, with its disk intact. Its log still contains offsets 8 to 12, the five messages that the rest of the cluster has never seen. Meanwhile the new leader has written different messages at offsets 8, 9, 10 and so on. Two copies now disagree about what lives at the same offsets. Kafka cannot keep both. The new leader’s history wins, and Broker 1 must cut its log back to the point where the two histories split. This cut is called log truncation.

How a returning replica finds the split point

Early versions of Kafka used the high watermark to decide where to cut. That approach had gaps, and in some rare timings it could leave replicas with different data at the same offset, which is a serious problem. Modern Kafka uses a more reliable tool called the leader epoch. An epoch is a counter that goes up by one every time a partition gets a new leader. Each batch of messages is stamped with the epoch of the leader that wrote it, and every broker keeps a small table that says which epoch started at which offset.

When Broker 1 returns, it does not simply start fetching. It first asks the new leader, “For the epoch I last knew about, at which offset did that epoch end?” The new leader answers using its table. In our story it answers that epoch 0 ended at offset 8. Broker 1 then truncates its log so that it ends at offset 8, throwing away offsets 8 to 12, and starts copying the new leader’s messages from there. After that, all replicas agree again.

Everyday analogy

Imagine a shared recipe book where every edition has a number. When one cook returns after a long trip, she says, “My book is from edition 0.” The head cook replies, “Edition 0 ended at page 8. Everything you wrote after page 8 is not in the current book.” She tears out the extra pages and copies the current edition from page 8 onwards. The edition numbers make it clear exactly where the two books stopped matching.

flowchart LR
  subgraph BEFORE["Before Broker 1 returns"]
    direction TB
    OB1["Broker 1 old log
offsets 0 to 12
epoch 0"] OB2["Broker 2 new leader
offsets 0 to 7 from epoch 0
then new data from epoch 1"] end subgraph STEP["Recovery steps"] direction TB Q["Broker 1 asks:
where did epoch 0 end?"] A["Broker 2 answers:
offset 8"] T["Broker 1 truncates
offsets 8 to 12"] Q --> A --> T end subgraph AFTER["After recovery"] direction TB AB1["Broker 1 log
offsets 0 to 7 old
then copy of the new leader"] AB2["Broker 2 leader
same history as Broker 1"] end BEFORE --> STEP --> AFTER
Figure 6. The returning replica uses the leader epoch to find where histories split, cuts its extra messages, and re-syncs.

Fencing: why an old leader cannot do harm

The epoch has a second job. It is used to fence out leaders that are outdated. Imagine a broker that was cut off from the network and does not know it has been replaced. It may still believe it is the leader and accept writes. Every request in Kafka carries the epoch it expects, and replicas reject requests that carry an older epoch than they know of. So the outdated leader cannot slip new writes into the cluster, and its ISR changes are refused by the controller. This stops a dangerous “two leaders” situation known as split brain.

!
Truncated data is really gone

Kafka deletes the truncated messages from the returning broker’s log. There is no recycle bin. If those messages matter, some teams copy the old broker’s log directory aside before restarting the broker, and then read it with Kafka’s log dump tools to work out what was lost. Doing this requires a clear head and a plan, so decide on it in your runbook before the incident, not during it.

11What Producers and Consumers Experience

Applications feel the election in different ways, and some of the effects are silent.

The producer’s side

During the moments when a partition has no leader, a producer receives retriable errors such as “leader not available” or “not leader or follower”. Well-configured producers retry automatically, and the messages wait in a memory buffer until a leader appears or the delivery timeout expires. With unclean election off, an offline partition can keep producers waiting for a long time, the buffer can fill up, and the application may start blocking or failing. With unclean election on, the wait is short, because a new leader appears quickly.

The important part is what the producer does not see. Messages that were confirmed before the election and then lost never send an error afterwards. The confirmation was true when it was given. The producer moves on with no clue that five of its messages no longer exist. Modern producers also enable idempotence by default, which prevents duplicate writes during retries, but idempotence does nothing to bring back messages that a lost leader held alone.

The consumer’s side

Consumers keep a position, which is the offset they will read next. That position is saved in Kafka in an internal topic named __consumer_offsets. After an unclean election, the log may be shorter than a consumer’s saved position. In our story, a consumer may have read up to offset 12 and saved position 13, but the new leader’s log ends at offset 8. When the consumer asks for offset 13, the broker replies that the offset is out of range.

The consumer then follows its auto.offset.reset policy. If the policy is latest, it jumps to the end of the log and skips whatever it has not yet seen. If the policy is earliest, it goes back to the start of the retained log and reprocesses a great deal. If the policy is none, it throws an error and lets the application decide. There is also a sneakier case. If new messages arrive fast enough that the log grows past the consumer’s saved position before the consumer asks again, the position looks valid, and the consumer would carry on from the wrong place with no error at all. Kafka closed this gap in version 2.1 by letting consumers send the leader epoch with their fetches, so that a truncation can be detected and either handled or reported.

Who is affectedWhat happens after an unclean electionIs there a loud error?
Producer with confirmed messagesSome of them no longer exist in the clusterNo
Consumer ahead of the new log endOut-of-range offset, then reset by policyYes, if no reset policy is set
Consumer whose position is now valid againMay skip or repeat records unless truncation is detectedOnly with epoch-aware detection
Compacted topic or changelogState can roll back to an older value for a keyNo
Stream processing jobLocal state may no longer match the input logSometimes
Downstream databases and search indexesHold rows that came from lost messagesNo

Effects on stateful systems

Stateful applications are hurt the most. A stream processing job may keep its running totals in a local store that is backed by a Kafka changelog topic. If that changelog loses its tail, the rebuilt store can differ from what the job computed earlier. Kafka’s exactly-once features assume that a message, once confirmed, stays confirmed. An unclean election breaks that assumption, so any guarantee built on top of it can quietly weaken. The internal topics that hold consumer offsets and transaction state deserve extra care for the same reason, and are normally configured with a high replication factor and strict settings.

Production example: an inventory service

An online retailer sends “stock reserved” and “stock released” events through Kafka. After an unclean election, a few “released” events vanish, while the “reserved” events that came before them were kept. The inventory service now thinks some items are still reserved and shows them as sold out, even though the customers cancelled. Nobody sees an error. The problem appears days later as a puzzling gap between the warehouse count and the website count.

12The Core Trade-off: Consistency or Availability

Every distributed system faces this choice. Unclean election is Kafka’s version of it.

The CAP theorem says that when a network splits or machines fail, a distributed system cannot promise both consistency and availability at the same time. Consistency means everyone sees the same, correct data. Availability means every request receives an answer. When failures strike, you must lean one way. Kafka’s default settings lean toward consistency for committed data: if it cannot guarantee that the next leader has everything, the partition waits. The unclean setting leans toward availability: the partition answers again quickly, even if that answer is built on a shorter history.

Stopping is a visible cost. Losing data quietly is a hidden one. Choose which cost your business can afford.

Reasons to allow unclean election

  • Partitions come back within moments, even after multiple broker failures.
  • Producers do not pile up in buffers or block their applications.
  • Good for high-volume data where a few lost records do not matter.
  • No need for an operator to make a decision at 3 a.m.
  • Consumers of live dashboards get fresh data sooner.

Reasons to forbid it

  • Confirmed messages can be lost with no error to anyone.
  • Consumers may read a rewritten history, with offsets that point at different data.
  • State in compacted topics and downstream systems can drift and stay wrong.
  • Auditing and reconciliation become hard, because the loss window is unknown.
  • Exactly-once and ordering guarantees can no longer be trusted.

A simple way to decide

Ask three questions about each topic. First, can the data be recreated from another source, such as the database that produced it? Second, what is the cost of a missing record, in money, trust or legal risk? Third, what is the cost of an hour of downtime for this stream? If the data can be recreated and downtime is costly, the permission may be reasonable. If the data cannot be recreated and a missing record is costly, keep the setting off. In many companies the answer differs for different topics, so the setting should be chosen topic by topic.

Kind of dataLoss hurtsDowntime hurtsSensible choice
Payments and ledgersVery muchMuchKeep unclean off, use strict durability settings
Orders and inventory eventsVery muchMuchKeep unclean off
Change data capture from a databaseMuchMediumOff, or on only if you can re-snapshot
Application logsLittleMediumCan be on
Metrics and telemetry samplesLittleMediumCan be on
Clickstream for analyticsLittleMediumCan be on

Production example: a video app’s viewing events

A streaming service records “play”, “pause” and “buffering” events from millions of devices so that analysts can study quality. If a partition loses a few seconds of these events, the charts hardly change, but if the partition stays offline, device apps may pile up data and the analytics pipeline falls behind. Companies with this kind of telemetry often decide that availability matters more, and they allow unclean election for those topics only, while keeping billing and account events strictly protected.

13Performance and Scalability: Keeping the ISR Healthy

The best way to avoid a bad election is to make sure the ISR rarely shrinks in the first place.

Unclean elections are the last domino in a row. The first domino is almost always a follower that cannot keep up. So performance work and safety work are really the same job. A cluster with enough headroom keeps its followers close to the leader, keeps its ISR full, and rarely faces the hard choice at all. The following ideas show how size and speed connect to the safety of your data.

What replication costs

Every byte written to a topic with a replication factor of 3 is stored three times and sent across the network twice more, from the leader to two followers. That means the cluster’s internal traffic is about twice its incoming traffic, on top of what consumers read. Disks must absorb the same amount of writing, three times over. If you plan capacity by looking only at the producer traffic, you will under-size the network and the disks, and the first sign of trouble will be followers dropping out of the ISR under load.

3x
disk writes for a topic with replication factor 3
2x
extra network traffic between brokers for every incoming byte
N+1
capacity plan: keep enough room to lose one broker at peak

Common design choices and their prices

ChoiceWhat you gainWhat it costs
acks=allConfirmed writes exist on several brokersLatency follows the slowest ISR member, so slow followers hurt producers
Minimum ISR of 2Never confirms a write held by only one brokerWrites pause when two brokers are unavailable
Replication factor 3Survives one broker failure with two copies leftUses three times the disk and extra network
Spreading across zonesSurvives a whole zone outageCross-zone latency and possible network charges
Short lag limit for followersFinds slow followers soonerMore ISR shrinking and growing during ordinary pauses
Many partitions per brokerMore parallelismMore work for elections, more files, slower recovery

Habits that keep followers close to the leader

  • Leave headroom. Plan for the cluster to run comfortably below its limits on normal days, so that a spike or a lost broker does not push it over the edge.
  • Tame pauses. Use a modern garbage collector, size the memory of the broker process sensibly, and leave plenty of memory for the operating system’s page cache, which Kafka depends on for fast reads and writes.
  • Use fast disks and enough network. Replication traffic competes with producer and consumer traffic, so separate or generous links help.
  • Throttle heavy maintenance. Moving partitions between brokers creates a lot of copy traffic. Kafka provides replication throttle settings, such as leader.replication.throttled.rate and follower.replication.throttled.rate, so that a rebalance does not starve normal replication and push followers out of the ISR.
  • Keep partition counts reasonable. A broker that leads or follows an enormous number of partitions has more to copy, more files to open and a slower failover.
  • Restart gently. Restart one broker at a time and wait for the under-replicated count to reach zero before moving on.
Everyday analogy

A restaurant kitchen that is booked to its limit cannot cope when one cook calls in sick. A kitchen with a little spare capacity absorbs the loss and keeps the orders flowing. Headroom feels like waste on a quiet day, but it is what keeps the whole team in step on a busy one.

Scaling the number of brokers

Adding brokers gives you more room, but new brokers start empty. Kafka does not move partitions on its own, so you must reassign some partitions to the new brokers. While that copying happens, the cluster is under extra load and the ISR of moving partitions is briefly bigger than usual. Do this in quiet hours, use throttles, and check the under-replicated metric between steps. Growing the cluster in small, planned steps is always safer than a large rebalance done in a hurry.

i
A useful rule of thumb

If your ISR shrink rate is not close to zero on an ordinary day, you are already living near the edge. Fix that before you debate the unclean setting, because a quiet ISR is the best protection against ever needing it.

14The Configuration Knobs That Decide Your Fate

Unclean election never works alone. Five settings work together, and you must read them as a team.

Whether you lose data in a bad moment depends on a handful of settings that interact with each other. Looking at unclean.leader.election.enable alone is like checking one lock on a door that has four locks. The table below lists the settings you should review together for every important topic.

SettingWhere it livesWhat it controlsSafe starting point
replication.factorTopicHow many copies of each partition exist3
min.insync.replicasTopic or brokerMinimum ISR size needed to accept writes when acks=all2
acksProducerHow many copies must confirm before the producer moves onall
unclean.leader.election.enableTopic or brokerWhether an out-of-sync replica may be promotedfalse
replica.lag.time.max.msBrokerHow long a follower may lag before leaving the ISRKeep the default unless you have evidence
broker.rackBrokerTells Kafka where each broker lives, to spread copiesSet to the zone or rack name
enable.idempotenceProducerPrevents duplicate writes when retryingtrue
delivery.timeout.msProducerHow long a producer keeps trying before giving upMatch your business tolerance
auto.offset.resetConsumerWhat to do when a saved offset is invalidDecide deliberately, not by default
Internal topic replication and ISR settingsBrokerProtects consumer offsets and transaction stateReplication factor 3, min ISR 2

The durability triangle

Three settings form a triangle that protects confirmed data: a replication factor of 3, min.insync.replicas of 2, and acks=all. Together they say, “A write is only confirmed when at least two brokers hold it.” With this triangle in place, losing any single broker cannot lose a confirmed message, and the write path pauses rather than confirming a message that lives on one machine. Add unclean.leader.election.enable=false and you have closed the fourth lock: a stale replica can never become the leader.

Everyday analogy

Think of a bank vault with three keys. The rule “at least two keys must be present to open the vault” is like min.insync.replicas=2. Even if one key holder is sick, the vault still works. But if two key holders are missing, the vault stays closed. The bank prefers a closed door to an open one that anyone can walk through. Unclean election is like allowing a person who does not hold a key to open the vault because the line at the door is getting long.

Two mistakes with min.insync.replicas

Setting min.insync.replicas equal to the replication factor sounds extra safe, but it means that a single broker failure blocks every write to the partition. This is rarely what people want. Setting it to 1 removes the protection, and lets one machine confirm writes on its own. The balanced choice for a replication factor of 3 is 2, which tolerates one failure for both reads and writes.

i
Changing settings safely

Topic-level values can be changed on a running cluster with the standard admin tools. Change one topic at a time, record who made the change and why, and set a reminder to review it. Any temporary exception made during an incident should carry an expiry date, so that it does not become permanent by accident.

Client settings that make trouble visible

Broker settings decide whether loss can happen. Client settings decide whether your applications notice it, survive it and recover from it. It is worth reviewing them as carefully as the broker side, because the same failure can be harmless for a well-built client and painful for a careless one.

SideHabitWhy it helps
ProducerCheck the result of every send, using a callback or by waiting on the futureErrors such as “not enough replicas” reach your code instead of vanishing
ProducerKeep retries on and idempotence enabledShort leader changes are absorbed without duplicates
ProducerChoose a delivery timeout that matches how long the business can waitA stuck partition fails loudly instead of hanging forever
ProducerAdd a sequence number or unique ID to important eventsDownstream systems can detect gaps and duplicates
ConsumerCommit offsets only after the work is doneA crash means reprocessing, not silent skipping
ConsumerHandle out-of-range and truncation errors on purposeYou decide whether to skip ahead, replay or raise an alarm
ConsumerMake processing idempotentReplays after an incident do no harm
ConsumerAlert on sudden jumps of the committed offset backwards or forwardsPoints to a reset caused by an election or a mistake

A word about auto.offset.reset. Choosing latest means that after an out-of-range error, the consumer skips to the newest data and may miss records. Choosing earliest means it replays everything still retained, which can be huge and can cause duplicates. Neither is right for every application. A payment processor may prefer to stop and raise an alarm, so that a human decides. A dashboard may prefer to jump to the latest data. The important point is to make the choice on purpose, write it down, and test it.

15Choosing the Right Setting for Each Workload

Different topics deserve different answers. Here is how to think about the common kinds.

Rather than using one cluster-wide answer, sort your topics into groups by how much a lost record and an hour of downtime would cost. The cards below describe the usual groups and the direction each one normally takes.

Keep off

Money movement

Payments, transfers, refunds and ledger entries. A lost record is a financial or legal problem. Use the durability triangle and forbid unclean election.

Keep off

Orders and inventory

Order placed, stock reserved, shipment created. Missing events create wrong stock counts and unhappy customers. Keep strict settings.

Keep off

Audit and security events

Login records, permission changes, access logs kept for compliance. Gaps in these records can fail an audit or hide an attack.

Keep off

Compacted state topics

Topics that hold the latest value per key, such as user profiles or stream job changelogs. Rolling back state causes long-lived wrong answers.

Consider on

Clickstream and analytics

Page views, taps and video events. A few lost events barely change the trend, and blocking producers may hurt user-facing apps more.

Consider on

Metrics and logs

Machine metrics and application logs where fresh data matters more than perfect history. Losing a small window is usually acceptable.

Consider on

Rebuildable caches

Streams that can be regenerated from a source of truth, such as search index updates. If lost, rerun the source and repopulate.

Case by case

Change data capture

Database changes streamed into Kafka. If you can re-snapshot the database, loss is repairable. If you cannot, treat it as critical.

A short method for deciding

1

List the topics

Write down every topic together with the team that owns it and the systems that read from it.

2

Find the source of truth

For each topic, ask where the data can be recovered from if Kafka loses it. A database, a file store or an upstream service may be able to replay it.

3

Price a loss and an outage

Estimate the cost of losing the last minute of data, and the cost of an hour when the topic is unavailable. Use rough numbers agreed with the business.

4

Pick a profile

Assign each topic to a durable profile or an availability profile, and write the settings down in a shared document.

5

Enforce and review

Apply the profiles through configuration management, alert on drift, and revisit the choices each quarter.

!
Do not decide by cluster

A single cluster often carries both a checkout stream and a debug log stream. Turning the permission on at the broker level exposes every topic that did not explicitly override it, including topics created later by other teams. It is safer to leave the broker default at false and enable the permission per topic, where the decision is visible and owned.

16Real-World and Industry Examples

How well-known organizations use Kafka, and what each one teaches about this trade-off.

LinkedIn: where Kafka began

LinkedIn built Kafka to move activity data such as page views, searches and operational metrics between its many services, and later handed it to the Apache community. Its clusters have been publicly described as handling trillions of messages per day. The lesson: when a system was born for high-volume activity data, availability was a natural priority, and the safer default arrived only as Kafka grew into a home for more critical data.

Netflix: very large event pipelines

Netflix has written publicly about its Keystone data pipeline, which uses Kafka to carry a very large stream of viewing and operational events to analytics and monitoring systems. Its engineers have described tuning such pipelines with availability in mind, because the services and devices sending events cannot afford to stall. The lesson: telemetry pipelines tend to favour staying up, while the systems that handle billing and accounts are treated separately and more carefully.

Uber: real-time trip and pricing data

Uber relies on Kafka to carry trip events, driver and rider location updates and data for real-time decisions across a large number of services. A company running so many different kinds of streams cannot use one setting for everything. The lesson: at this size, teams separate critical streams, like payments, from high-volume streams, like location pings, and give each its own durability profile and clear ownership.

Banks and payment platforms

Financial firms that use Kafka for transaction streams, fraud checks and settlement usually insist on a replication factor of 3, a minimum ISR of 2, acks=all and unclean election disabled. They often add a second cluster in another region using a replication tool such as MirrorMaker 2, so that a whole-site disaster does not lose data. The lesson: for money, the design assumes that a short outage is acceptable and a lost record is not.

E-commerce sale events

A large online retailer during a sale season may run its order and payment topics on strict settings while running its page-view and recommendation click topics on relaxed ones. When a rack fails on the busiest night, the order topics may stall for a short period, while the click topics recover instantly. The lesson: the same cluster can safely serve both worlds, provided each topic knows which world it belongs to.

i
A note on these examples

The descriptions above summarize the general and public purpose of Kafka at each organization, and the lessons are common patterns in the industry. Internal settings of any particular company can change over time, so treat them as teaching examples, and check current public engineering posts if you need exact details.

17Security and Operational Safety

A durability setting is also a security control. Someone who can change it can quietly weaken your guarantees.

It may seem strange to talk about security in a chapter on leader election, but the two are close neighbours. A configuration change that turns the unclean permission on for a sensitive topic does not raise any alarms and changes nothing you can see. It just makes a future failure more damaging. That makes it an attractive target for accidents, and also for anyone who wants to cause harm without being noticed. Treat these settings with the same care as a firewall rule.

Who may change these settings

Kafka supports access control lists, called ACLs, that decide which users may perform which actions. Changing topic configuration and triggering leader elections are powerful administrative actions. They require permissions such as altering configuration on a topic, or altering the cluster as a whole. Give these permissions to a small group of platform engineers and to automation accounts, not to every application team. Application service accounts should only need to produce and consume.

Access

Least privilege

Applications get produce and consume rights on their topics only. Only the platform team and deployment tools may alter configuration.

Change control

Configuration as code

Keep topic settings in version control. Every change is reviewed, approved and traceable, and drift from the recorded values raises an alert.

Audit

Record every change

Turn on authorizer logging and keep a history of who changed what and when. Send it to the same place as your other security logs.

Transport

Encrypt broker traffic

Use TLS between brokers and clients and between brokers themselves, so replication traffic cannot be read or tampered with.

Identity

Authenticate everything

Require every client and every broker to prove who it is, using certificates or a trusted single sign-on scheme.

Guardrails

Block risky defaults

Use policies or automation that reject topics created with a replication factor below 3 or with the unclean permission turned on.

Security effects of a rolled-back history

Losing or rewinding data can be a security problem too. Imagine a topic that carries “this access token was revoked” events, or “this account was locked” events. If an unclean election loses the tail of that topic, the consumers may never learn that a token was revoked, and a door that should be closed stays open. The same is true for compacted topics that hold the latest permission state for each user. A rolled-back value can bring back an old permission. For this reason, security-related event streams belong firmly in the strict group.

!
Emergency changes need an owner and an end date

During an incident, a tired engineer might switch the unclean permission on to get a topic back. That can be the right call, but only if the change is written down, announced to the topic owner, and reverted as soon as the cluster is healthy. Build this step into your runbook, and add a scheduled check that flags any topic still carrying the permission after the incident is closed.

18Monitoring, Logging and Metrics

You cannot fix what you cannot see, and unclean elections are quiet by nature.

Because an unclean election does not raise an error for producers or consumers, the only reliable way to notice it is to watch the cluster itself. Kafka brokers and controllers publish metrics that describe leader elections, ISR changes and offline partitions. Set up alerts on the following ones. Names can differ slightly between Kafka versions, so confirm them in the documentation for the version you run.

MetricWhat it tells youSuggested alert
UncleanLeaderElectionsPerSecCounts unclean elections on the controllerPage immediately on any value above zero
OfflinePartitionsCountNumber of partitions with no leaderPage if above zero for more than a short grace period
UnderMinIsrPartitionCountPartitions whose ISR is below the minimumAlert as a high-priority warning
UnderReplicatedPartitionsPartitions with fewer in-sync copies than plannedAlert if it stays above zero
IsrShrinksPerSec and IsrExpandsPerSecHow often followers leave and rejoin the ISRAlert on unusual rates or repeated flapping
ActiveControllerCountWhether exactly one controller is activeAlert if the total across the cluster is not one
LeaderElectionRateAndTimeMsHow often elections happen and how long they takeAlert on spikes or long durations
flowchart LR
  BR["Brokers and Controller
publish metrics and logs"] --> MC["Metrics Collector
Prometheus or similar"] BR --> LG["Log Aggregator
controller and state change logs"] MC --> AL{"Offline partitions or
unclean elections above zero?"} LG --> AL AL -->|"Yes"| PG["Page the on-call engineer"] AL -->|"No"| DB["Dashboards and daily review"] PG --> RB["Follow the runbook
scope, recover, reconcile"]
Figure 7. Metrics and logs feed one alert rule. Any sign of an unclean election pages a person who follows a written runbook.

What to look for in logs

The controller log and the state change log record every change of leader and ISR. During an incident, search for partitions that moved from offline to online with an ISR of just one member, since that is the fingerprint of an unclean election. On the returning broker, look for lines that mention truncating a partition to a particular offset. They tell you exactly where the log was cut, and they help you work out the size of the lost window.

Watch the early signs, not only the disaster

An unclean election is the last step in a chain. Long before it, you will usually see the ISR shrink and grow again, followers lag more than usual, and disks or networks show stress. Alerting on those early signs gives you time to act. A very useful habit is to keep a dashboard that shows, for each important topic, the number of partitions whose ISR is smaller than the replication factor.

Test for loss from the outside

Broker metrics show what Kafka believes. A small test program shows what applications experience. Write a canary that produces numbered messages at a steady pace into a strict topic and consumes them back, watching for gaps or repeats in the numbers. If a number ever goes missing, you have found data loss even if every metric looked clean. Some teams also add sequence numbers to their real events, so that downstream systems can detect gaps on their own.

i
Do a fire drill

In a test cluster, kill brokers on purpose in different orders and watch what your alerts, dashboards and applications do. It is much better to learn that an alert never fires during a drill than during a real outage.

19Failure Scenarios and Recovery Playbook

Real failures come in many shapes. Here are the ones that lead to unclean elections, and what to do afterwards.

ScenarioCauseUnclean offUnclean on
Restarting brokers too fastA rolling restart moves to the next broker before the last one has rejoined the ISRPartitions go offline brieflyA behind replica may lead and lose the recent tail
Availability zone outageA power or network failure takes out one zone, and another broker is slowSome partitions offline until the zone returnsPartitions return at once, with possible loss
Lost disk on the only in-sync brokerHardware failure while the ISR was down to onePartition stays offline until you decideAn older replica takes over automatically
Long pauses on followersGarbage collection or a busy disk pushes followers out of the ISRWrites may be refused if min ISR is met poorlySame, plus higher risk if the leader then dies
Network split from the controllerOld leader is cut off and a new one is chosen elsewhereOld leader is fenced by the epochSame fencing, but the new leader may be behind

The recovery playbook

When a partition goes offline, the choice is not between “enable the permission” and “do nothing”. There is a better order of steps, and it helps to have it written down before you need it.

1

Find the scope

List the offline partitions and the topics they belong to. Note which brokers were in the ISR last and how each one failed.

2

Try to bring back the last in-sync broker

Restart it, repair its network, or move its disk to a new machine. A recovered ISR member gives you a clean election with no loss.

3

Set a time limit

Agree with the topic owner how long the business can wait. Availability may be worth more than a bit of data once that limit is reached.

4

Preserve evidence

If the old leader’s disk is readable, copy its log directory before restarting it, so that you can later find out what was in the lost range.

5

Run a targeted unclean election

If you must proceed, trigger the election only for the affected partitions, or enable the permission on those topics only. Record the time.

6

Turn the permission back off

Once partitions have leaders and ISRs recover, restore the strict setting, and confirm the change with a configuration check.

7

Reconcile the data

Work out the lost offset ranges and time window. Replay from the source of truth, ask upstream systems to resend, or compare downstream counts.

8

Fix consumers

Check consumers for out-of-range offsets, and decide whether to reset them. Look at stream jobs with local state and rebuild if needed.

9

Write the post-incident review

Record the causes, the size of the loss and the changes that would have prevented it, such as a higher minimum ISR or slower restarts.

flowchart TD
  S["Partition offline"] --> Q1{"Can the last ISR broker
be brought back in time?"} Q1 -->|"Yes"| R1["Restore it and let a clean election happen
no data loss"] Q1 -->|"No"| Q2{"Can the business accept
possible loss on this topic?"} Q2 -->|"No"| W["Keep waiting and escalate
restore from backup or upstream source"] Q2 -->|"Yes"| U["Preserve old logs, then run a targeted
unclean election for this topic only"] U --> V["Restore strict setting after recovery"] V --> Z["Reconcile lost range and fix consumers"]
Figure 8. A decision path for an offline partition. Waiting for a trusted copy is always tried first.

Production example: a rolling upgrade gone wrong

A platform team upgrades a ten-broker cluster one broker at a time. Broker 4 is restarted, but the script moves on to Broker 5 before Broker 4 has fully caught up. For a short window, several partitions have an ISR of one, and a network blip then hides the last in-sync broker. With strict settings, those partitions pause for a few minutes until the broker returns. With relaxed settings, they resume at once, and a slice of recent events is lost. The lesson: make your upgrade script wait until there are no under-replicated partitions before touching the next broker.

20Design Patterns and Anti-Patterns

Habits that keep data safe, and habits that cause the loss stories you read about.

Patterns that work

Pattern

The durability triangle

Replication factor 3, minimum ISR 2, acks=all, unclean election off. It survives any single broker failure without losing a confirmed message.

Pattern

Spread across zones

Set broker.rack for every broker and place copies in different zones, so one zone outage leaves at least one in-sync copy alive.

Pattern

Idempotent consumers

Design consumers so that seeing the same event twice does no harm. This makes replays after an incident safe.

Pattern

Source of truth outside Kafka

Keep the master copy of important data in a database. Use an outbox table or change data capture to publish it, so Kafka can be refilled.

Pattern

A second cluster

Copy critical topics to another cluster or region using MirrorMaker 2 or a similar tool, to survive site-level failures.

Pattern

Topic profiles

Define named profiles, such as “critical” and “telemetry”, each with fixed settings. Teams choose a profile instead of inventing values.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What people do

They switch on the unclean permission for the whole cluster after one painful outage, so that partitions “never go offline again”.

Why it hurts

Every topic, including payments and audit logs, now accepts a stale leader. The next multi-broker failure can silently rewrite history for streams that were never meant to take that risk.

Do this instead

Keep the broker default at false. Enable the permission on named telemetry topics only, and use targeted on-demand elections for emergencies.

ANTI-PATTERN 02Avoid
What people do

They create topics with a replication factor of 2, or with a minimum ISR of 1, to save disk space or to avoid producer errors.

Why it hurts

With two copies and a minimum ISR of 2, one failure stops all writes. With a minimum ISR of 1, a single machine can confirm writes alone, which is the exact ingredient that makes unclean loss possible.

Do this instead

Use a replication factor of 3 and a minimum ISR of 2 for anything you cannot afford to lose. Accept the extra disk cost as insurance.

ANTI-PATTERN 03Avoid
What people do

They enable the permission during an incident and never turn it off, and nobody tells the topic owner.

Why it hurts

The exception becomes the rule. Months later, a new failure causes data loss on a topic whose owners believe it is fully protected.

Do this instead

Attach an owner and an end date to every emergency change. Add an automated check that lists topics with the permission turned on and sends it to the owners each week.

ANTI-PATTERN 04Avoid
What people do

They treat Kafka as the only copy of important data and never plan how to rebuild it.

Why it hurts

When a loss happens, there is nothing to replay from, and the gap can never be closed.

Do this instead

Know where each stream can be regenerated from, and practise the replay before you need it.

21Best Practices and Common Mistakes

A checklist you can take to your next design review.

Do

  • Use a replication factor of 3 and a minimum ISR of 2 for important topics.
  • Keep unclean.leader.election.enable at false by default.
  • Give producers acks=all and idempotence.
  • Spread brokers over zones and set broker.rack.
  • Wait for zero under-replicated partitions between broker restarts.
  • Alert on every unclean election and every offline partition.
  • Write a runbook and practise it in a test cluster.
  • Store configuration in version control and audit changes.
  • Protect internal topics with the same strict settings.

Avoid

  • Turning the permission on cluster-wide to hide availability problems.
  • Setting the minimum ISR to 1 while claiming strong durability.
  • Using acks=1 for data that matters.
  • Restarting several brokers at the same time.
  • Ignoring ISR shrink alerts because “the cluster still works”.
  • Leaving auto.offset.reset at a default nobody chose.
  • Forgetting emergency changes after the incident.
  • Depending on Kafka as your only source of truth.
  • Letting every team change topic settings freely.

Common mistakes in more detail

Mistake one: believing that acks=all is enough. As you saw in chapter 5, acks=all only waits for the members of the ISR. If the ISR is small and the permission is on, a confirmed message can still disappear. The protection comes from the whole set of settings, not from one of them.

Mistake two: not testing multi-failure cases. Most teams test the loss of one broker, which Kafka handles gracefully. Unclean elections come from the second and third failures, which are rare and rarely tested. Include double failures in your drills.

Mistake three: forgetting the internal topics. The topics that store consumer offsets and transaction state are just as vulnerable. Losing consumer offsets can make an entire consumer group reprocess or skip data. Check that their replication factor and minimum ISR are set as strictly as your important data topics.

Mistake four: ignoring the consumer side. Even with strict settings, an unexpected loss can happen through hardware fault or human error. Consumers should have a deliberate policy for out-of-range offsets, and applications should be able to detect gaps through sequence numbers or reconciliation jobs.

Mistake five: measuring availability without measuring durability. A dashboard that reports 100 percent uptime says nothing about lost records. Track both, and give durability the same seriousness as availability.

22Where Kafka Is Heading: KRaft and Smarter Recovery

The mechanics of who leads a partition keep evolving, though the core trade-off stays the same.

For many years, Kafka relied on ZooKeeper to store cluster information and to help pick a controller. Modern Kafka replaces it with KRaft, where a small group of controller servers keep the cluster’s metadata in their own replicated log and use the Raft consensus method to agree on changes. Kafka 4.0 and later run in KRaft mode only. In this design, the active controller records leader changes as entries in the metadata log, and brokers read those entries to learn about new leaders. Failovers can be quicker in large clusters with many partitions, because the metadata is already replicated and ready.

The rules for unclean election did not change with KRaft. The controller still prefers an ISR member, still resets the ISR to the new leader when it has to go outside it, and the same setting still controls the permission. What improves is the speed and the clarity of the process, not the underlying trade-off between keeping data and staying available.

Everyday analogy

Changing from ZooKeeper to KRaft is like a company that used to keep its official records in an outside office and now keeps them in a small trusted committee inside the building. Decisions are faster and there is one fewer thing to look after, but the rule for choosing a new team leader is the same as before.

Ideas to make recovery smarter

The Kafka community has been exploring ways to lower the need for risky elections. One such proposal, known as eligible leader replicas (KIP-966), aims to keep track of which replicas are known to hold all committed data, even after the ISR has shrunk. With that memory, the controller could pick a safe leader in more situations, and leave fewer partitions stuck offline. The status of ideas like this changes between releases, so read the release notes for your version before relying on them.

Other trends help indirectly. Follower fetching lets consumers read from a nearby replica, which can reduce cross-zone traffic. Tiered storage moves old data to cheaper storage, which makes brokers lighter and faster to recover. Better tools for rolling restarts and rebalancing reduce the number of times that a cluster is exposed to risk. None of these removes the need to understand unclean elections, but together they make the dangerous situation less common.

23Worked Example: Topic Profiles for an Imaginary Online Shop

Let us put everything together on a made-up company, so that the ideas turn into real decisions.

Imagine a fictional shop called FreshCart that sells groceries online. It has a website, a mobile app, a warehouse system and a small data team. Its Kafka cluster has six brokers spread over three availability zones, two brokers in each. The platform team wants clear rules for the topics that different teams create. Instead of arguing about each topic, they define two named profiles. The critical profile uses a replication factor of 3, a minimum ISR of 2 and unclean election off. The telemetry profile uses a replication factor of 3, a minimum ISR of 2 and unclean election on. Both use zone-aware placement, so the difference is only in how they behave when almost everything has failed.

TopicWhat it carriesCan it be rebuilt?Profile
paymentsCard charges and refundsPartly, from the payment providerCritical
ordersOrders placed, changed and cancelledYes, from the orders database with effortCritical
inventory-eventsStock reserved and releasedYes, by recounting the warehouseCritical
user-permissionsLatest access rights per user (compacted)Yes, from the identity systemCritical
audit-logWho did what in internal toolsNoCritical
page-viewsClicks and views on the websiteNo, but nobody needs each oneTelemetry
search-queriesWhat shoppers typed into searchNo, but statistics are enoughTelemetry
app-logsDebug and error logs from servicesNo, and short-lived by natureTelemetry
delivery-van-locationsGPS pings from vansNo, the next ping replaces the lastTelemetry

Why these choices make sense

The first five topics are either money, stock counts, permissions or legal records. A lost record here creates a wrong answer that can last for a long time, so these topics would rather wait than guess. The last four topics describe things that are either high in volume, quickly out of date or only useful in bulk. If one partition of delivery-van-locations loses ten seconds of pings, the map on a customer’s phone simply shows a slightly older position until the next ping arrives. Blocking the whole location pipeline to protect ten seconds of pings would be a bad trade.

A bad night in the data centre

Now imagine that a power fault takes out one whole zone during a sale, and at the same moment a broker in another zone is paused by a long garbage-collection cycle. Some partitions have lost two of their three copies, and the last one is behind. Here is what each group of topics experiences.

Topic groupWhat Kafka doesWhat the business sees
Critical topicsPartitions without an in-sync replica stay offline. Others carry on after a clean election.A short pause in some checkouts. No confirmed payment or order is lost. Engineers restore the broker and traffic resumes.
Telemetry topicsAll partitions come back at once, some through unclean elections.Charts show a small hole of a few seconds. Nobody outside the data team notices.

What the team does the next morning

The on-call engineer sees that the unclean election metric rose for three telemetry partitions, exactly as the runbook predicted. She notes the time window in the incident record, tells the analytics team that a few seconds of page views are missing, and checks that no critical topic shows the same metric. Because the profiles were chosen in advance, the review takes twenty minutes instead of a long argument.

A tabletop exercise you can run with your own team

You can practise the same story without touching a real cluster. Gather the platform team and a few application owners in one room, and read out a failure one step at a time: “A zone is down. Two brokers are gone. A third is paused. Which of your topics are offline? Which came back through an unclean election? What do your consumers do next?” For each topic, ask the owner to say aloud what they would check and what they would tell the business. Gaps in the answers show you where the runbook, the alerts or the topic settings need work. Repeat the exercise every quarter, with a different failure each time.

i
Write the profile into the topic

Give each topic a label or naming rule that shows its profile, such as a prefix or a tag in your configuration repository. When a new team creates a topic, the tooling should ask them to pick a profile and refuse to continue without one. A choice that is easy to see is a choice that is easy to review.

24Frequently Asked Questions

Q1Does turning the setting on make Kafka run unclean elections regularly?
No. It is only a permission. Kafka uses it when the leader is gone and no in-sync replica is alive. On a healthy cluster it may never be used.
Q2What is the default value?
The default is false, and has been since Kafka 0.11.0. Earlier versions defaulted to true. You should still check your own cluster and topic values instead of trusting the default, since someone may have changed them.
Q3Is data loss certain if an unclean election happens?
No. Loss happens only if the chosen replica is missing messages. A replica that sat outside the ISR for a moment may be fully up to date. But Kafka cannot prove that, which is why the loss is possible.
Q4If I use acks=all and a minimum ISR of 2, am I safe with the setting on?
Not completely. Each confirmed message lives on at least two brokers. If both of those brokers fail and only a lagging third replica survives, an unclean election would promote it, and the message is gone. The settings protect you from a single failure, not from every double failure.
Q5Can I set it for one topic only?
Yes. It can be set as a topic-level override, and changed while the cluster runs. This is the recommended way to allow it for telemetry-style topics while keeping everything else strict.
Q6What about the internal topics for consumer offsets and transactions?
Keep them strict. Losing consumer offsets can make groups reprocess or skip data, and losing transaction state can undermine exactly-once processing. Give them a replication factor of 3 and a sensible minimum ISR.
Q7Does KRaft change how unclean elections work?
The rules and the setting are the same. The difference is where the cluster metadata is stored and how the controller coordinates. The trade-off between safety and availability is unchanged.
Q8How do I know that an unclean election happened?
Watch the unclean leader election rate metric on the controller, look for partitions that came online with a single-member ISR in the controller and state change logs, and look for truncation messages on returning brokers.
Q9Will my consumers notice the loss?
Sometimes. Consumers ahead of the new log end get an out-of-range error and follow their reset policy. Since Kafka 2.1, consumers can also detect truncation using the leader epoch. But consumers that were behind the loss point may notice nothing at all.
Q10Is a replication factor of 2 acceptable?
For data that matters, it is a weak choice. With a minimum ISR of 2, one failure stops writes. With a minimum ISR of 1, one machine can confirm alone. A replication factor of 3 gives you room to lose one broker and still keep two copies.
Q11How is this different from preferred leader election?
Preferred leader election moves leadership to the first replica in the list when it is in sync, to balance load. It never picks an out-of-sync replica and does not lose data. Unclean election is an emergency path that does.
Q12Should I enable it during an outage to get back online?
Only after trying to restore the last in-sync broker, and only with the topic owner’s agreement. Prefer a targeted election on the affected partitions, preserve the old logs if you can, and turn the strict setting back on afterwards.
Q13Can lost messages be recovered?
Not from the cluster. They can only come from a source of truth that can replay them, from another cluster that mirrored the topic, or from the old leader’s log files if you saved them before truncation.
Q14Does it affect exactly-once processing?
Yes. Exactly-once features assume that confirmed data stays confirmed. If an unclean election removes confirmed messages, those guarantees no longer hold for the affected range.
Q15Does the setting matter when the replication factor is 1?
No. With a single copy there is no other replica to promote. If that broker fails, the partition is offline until the broker returns, and if its disk is lost, the data is lost regardless of any election setting.
Q16Can I change the setting on a running cluster?
Yes. It is a dynamic setting that can be changed for one topic or for all topics without a restart. That convenience is exactly why changes must be tracked, reviewed and reverted when they were meant to be temporary.
Q17What happens to messages that were only on the old leader during a clean election?
If they were not committed, the producer was not told they were safe, and it can retry them. When the old leader returns, it cuts its log back to match the new leader, so those uncommitted extras disappear. Committed messages are never affected in a clean election.
Q18Is this only a concern for very large companies?
No. A small team with three brokers and a shop, a game or a banking app faces the same choice. In fact, small clusters have fewer spare brokers, so they are more likely to end up with a single surviving copy after a bad night.

25Summary and Key Takeaways

Everything in this guide can be held in a few sentences.

Key Takeaways

  • Definition. An unclean leader election promotes a replica that is outside the ISR, so the new leader may be missing messages that were already confirmed.
  • Two conditions. It happens only when the leader is gone, no in-sync replica is alive, and unclean.leader.election.enable is true for that topic.
  • Silent loss. Producers and consumers receive no error at the moment of loss. The ISR is reset to the new leader, and returning replicas truncate their extra data using the leader epoch.
  • A trade-off, not a bug. The setting exchanges data safety for availability. Default false favors consistency, and true favors uptime.
  • Settings work as a team. Replication factor 3, minimum ISR 2, acks=all and unclean off protect against a single failure. Turning unclean on weakens all of them during double failures.
  • Choose per topic. Keep payments, orders, audit and state topics strict. Allow the permission only for disposable telemetry, and give every exception an owner and an end date.
  • Watch and rehearse. Alert on any unclean election and any offline partition, keep a written runbook, and know where lost data can be replayed from.