Metadata Caching on Brokers in Kafka

Metadata Caching on Brokers in Kafka

Every produce and fetch request in Kafka begins with a question: who is in charge of this partition right now? This guide explains how brokers answer that question in microseconds from a local copy, how that copy stays fresh, and what happens when it goes stale.

Imagine walking into a huge airport with no signs. Before you can board, you must find your gate, and the only way is to phone the central control room and ask. Now imagine ten thousand passengers doing the same thing every few seconds. The control room would drown in calls, and every flight would be late.

Real airports solve this with departure boards. The control room decides which flight uses which gate and sends updates to screens in every terminal. Passengers read the nearest screen, which is fast and needs no phone call. Apache Kafka works the same way. A small group of machines decides who leads each partition, and every broker keeps its own local copy of those decisions, called the metadata cache.

This guide explains that cache from the ground up: what is stored in it, how updates travel to every broker, how clients keep their own second copy, what goes wrong when copies disagree, and how to configure and monitor it in production. Each new term is explained when it first appears, and each big idea comes with an everyday comparison and real-world context.

KKafka in Five Minutes

A short refresher on the moving parts, so that the rest of the guide has firm ground to stand on.

Apache Kafka moves streams of events between programs. A program that writes events is a producer, and a program that reads them is a consumer. The servers that store the events are brokers, and a group of brokers is a cluster. Events are organised into named streams called topics, and each topic is cut into partitions, which are ordered lists of messages that can live on different brokers so the work can be shared.

For safety, every partition is copied to several brokers. Each copy is a replica. One replica is the leader and handles all reads and writes for that partition. The others are followers that copy the leader. The set of replicas that are keeping up is the in-sync replica set, or ISR.

Everyday analogy

Picture an airline with many flights. A topic is a route, a partition is one specific flight on that route, and the leader is the gate where boarding for that flight happens. Passengers can only board at the right gate. If they walk to the wrong one, they are politely sent away.

Writer

Producer

Sends messages to a partition. It must know which broker currently leads that partition.

Reader

Consumer

Reads messages from a partition leader, and also needs to find its group coordinator.

Server

Broker

Stores partitions and answers requests. Every broker knows about the whole cluster, not only its own data.

Stream

Topic and partition

A topic is split into partitions. Order is kept inside a partition, and partitions spread across brokers.

Copies

Replicas

Several copies of each partition on different brokers, with one leader and the rest followers.

Guide

Metadata

The map that says which topic exists, where each partition lives, and who leads it right now.

i
The key question

Every client action in Kafka starts with “where do I send this?” The answer lives in the metadata. Everything else in this guide is about how that answer is stored, spread, kept fresh and used safely.

WWhat Is Kafka Metadata?

Metadata means “data about data”. In Kafka it is the description of the cluster itself, not the messages inside it.

Your messages are the cargo. The metadata is the map of the airport: which gates exist, which flight uses which gate, and which staff are on duty. It is small compared with the cargo, but without it nothing can be delivered. Kafka keeps several kinds of metadata, and each kind answers a different question.

Kind of metadataQuestion it answersExample
Broker listWhich brokers are alive and at what addresses?Broker 1 at host-a:9092, Broker 2 at host-b:9092
Topics and partitionsWhat topics exist and how many partitions has each?Topic orders has 12 partitions
Leaders and epochsWho leads each partition, and under which leader epoch?Partition 3 of orders: leader Broker 2, epoch 7
Replicas and ISRWhere are the copies and which are in sync?Replicas on brokers 1, 2, 3; ISR is 2 and 3
ConfigurationWhich settings apply to a topic or broker?Retention of seven days on orders
Access rulesWho may read, write or administer what?Service payments may write to orders
QuotasHow much traffic may a client use?Client reporting is limited to a set bandwidth
Feature levelsWhich cluster-wide features are turned on?The metadata version the cluster runs at
Small
metadata is tiny next to the message data it describes
Hot
it is consulted on nearly every request a client sends
Shared
every broker needs the same picture of the whole cluster

Why every broker needs the whole picture

A broker stores only some partitions, yet it must know about all of them. A client may connect to any broker and ask about any topic, so each broker must be able to answer for the whole cluster. A broker also has to check, on every produce or fetch request, whether it is the correct leader for the partition being asked about, and it must reject requests that arrive at the wrong place. These checks happen thousands of times a second, and they all read the metadata.

i
Metadata changes slowly, and is read constantly

A topic is created once but used millions of times. A leader changes only during failures or maintenance but is checked on every request. This pattern, rare writes and enormous reads, is the perfect situation for a cache.

PThe Problem a Cache Solves

To see why brokers keep a local copy, imagine the design without one.

Suppose the truth about the cluster lived in one place, and every broker had to ask that place a question each time a request arrived. A single busy broker may handle tens of thousands of requests each second. Multiplied across a cluster with dozens of brokers, that is a flood of lookups aimed at one small service. The lookups would add delay to every request, and the service would become both a bottleneck and a single point of failure.

Everyday analogy

It is the phone-the-control-room airport again. The control room knows everything, but it can only answer so many calls. Departure boards fix this by copying the answers to where people need them. The control room now speaks only when something changes, and reads happen locally at the speed of looking at a screen.

What a cache buys

Speed

Lookups in memory

Reading a value from the broker’s own memory takes far less time than a network call. Checking the leader of a partition becomes nearly free.

Scale

Load spread across all brokers

Any broker can answer a metadata question, so client questions are spread over the whole cluster, not aimed at one machine.

Resilience

Work continues during trouble

If the controller is briefly busy or changing over, brokers still serve requests from what they already know.

Simplicity

Any broker as an entry point

A client needs only one working address to find out about the entire cluster. That address can be any broker.

What a cache costs

A copy can become out of date. If the control room changes a gate and one screen has not updated yet, a passenger may walk to the wrong place. Kafka accepts this, because a wrong answer is cheap to correct: the request is rejected with a clear error, the client asks again, and the next answer is right. The rest of this guide is about making those corrections quick, safe and rare.

Pros of a local cache

  • Very fast reads from memory
  • Load is spread across every broker
  • Clients need only one bootstrap address
  • Brokers keep working through short controller hiccups

Cons of a local cache

  • Copies can briefly disagree
  • Stale answers cause errors and retries
  • Updates must reach every broker reliably
  • Memory grows with the number of partitions

BThe Broker Metadata Cache at a Glance

Here is the whole system in one picture, followed by a walk through each part.

flowchart LR
  CQ["Controller quorum
holds the metadata log"] -->|"metadata records"| B1["Broker 1
local metadata cache"] CQ -->|"metadata records"| B2["Broker 2
local metadata cache"] CQ -->|"metadata records"| B3["Broker 3
local metadata cache"] P["Producer"] -->|"Metadata request"| B1 C["Consumer"] -->|"Metadata request"| B2 A["Admin tool"] -->|"Metadata request"| B3
Figure 1: the controller quorum decides and records changes. Every broker keeps a local cache, and clients ask any broker.

Read the figure from left to right. On the left is the controller quorum, a small group of servers that makes decisions about the cluster and records each decision in an ordered log. In the middle are the brokers. Each one reads that log and builds its own in-memory picture of the cluster, which is the metadata cache. On the right are the clients. They send Metadata requests to whichever broker they can reach and receive answers straight from that broker’s cache.

Two layers of caching

There are really two caches involved, and it helps to keep them apart. The first lives inside every broker, and it is a copy of the cluster’s state. The second lives inside every client, and it is a copy of the parts of that state the client cares about. A client asks a broker, keeps the answer for a while, and reuses it. The airport version: the broker cache is the departure board, and the client cache is the gate number printed on the passenger’s boarding pass.

CacheWhere it livesWho fills itHow it is kept fresh
Cluster state cacheInside each broker’s memoryThe controller, through the metadata logBrokers apply new records continuously
Client metadata cacheInside each producer, consumer or admin clientAny broker, through Metadata requestsPeriodic refresh and refresh on errors
i
Not the same as the page cache

Kafka also relies heavily on the operating system’s page cache, which holds recent message data in memory for fast reads and writes. That is a different thing. In this guide “metadata cache” always means the cluster map, not the message data.

CThe Controller: Source of Truth

Caches are copies, and copies need an original. In Kafka, the original is managed by the controller.

The controller is the part of the cluster that makes decisions about the cluster itself. It reacts when a broker joins or fails, chooses a new leader when one is lost, creates and deletes topics, changes partition counts, and updates configuration. Brokers do not make these decisions on their own, because two brokers deciding differently would leave the cluster in conflict. One authority avoids that.

The word controller has meant two slightly different things over the years. In older clusters, one ordinary broker was elected controller and used an external coordination service called ZooKeeper to store cluster state. In modern clusters, a dedicated group of controller nodes runs a built-in consensus protocol called KRaft and keeps the state in Kafka’s own log. Only one controller is the active one at a time. The others are ready to take over.

Everyday analogy

The controller is the airport’s operations centre. It assigns gates, reacts when a plane is cancelled, and announces changes. There is only one operations centre in charge at a time, with a backup team ready, so announcements never contradict each other.

What the controller must guarantee

Order

One order of events

Every change is placed in a single, ordered sequence. Every broker applies the same changes in the same order, so all caches converge to the same picture.

Durability

Decisions survive crashes

A decision is safely stored before anyone is told about it, so a controller failure cannot erase or reverse it.

Single authority

No two active controllers

A numbered term or epoch identifies the current controller, so a stale one that wakes up late is ignored.

!
The controller is not on the data path

Producers and consumers do not talk to the controller when sending or reading messages. The controller only makes and records decisions. This is exactly why brokers cache its decisions: so that the busy data path never has to wait on it.

DDeployment Shapes: Who Runs the Controller?

The same software can run in different roles. How you arrange those roles decides how well the metadata system copes with load and failure.

In modern Kafka, a server process can be given one or more roles. A broker role stores partitions and serves clients. A controller role takes part in the quorum that makes and records cluster decisions. A single process can hold both roles, called combined mode, or each can run on its own machines, called dedicated mode.

ShapeHow it looksBest suited forMain risk
CombinedEach node is both broker and controllerDevelopment, tests, small clustersHeavy data traffic can starve the controller, and a broker problem also hurts the quorum
Dedicated controllersThree or five small nodes run only the controller role, separate from brokersProduction, especially larger clustersExtra machines to run and secure
Everyday analogy

In a small regional airfield, one person may both direct planes and load luggage. In a big international airport, the control tower is a separate building with its own staff, so a luggage jam can never delay a takeoff decision.

How many controllers?

The controller quorum needs a majority of its members to agree before any decision is committed. That is why quorums use an odd number of nodes. With three controllers, a majority is two, so the quorum tolerates the loss of one node. With five controllers, a majority is three, so it tolerates the loss of two. More than five brings little benefit, since each additional member adds more communication to every decision.

3
controllers
tolerates 1 failure
5
controllers
tolerates 2 failures
Odd
numbers only, since an even count adds cost without adding tolerance

What brokers need from the controllers

Brokers are not voters. They do not count toward the majority. They only need to reach the active controller to fetch the metadata log, to register, and to send heartbeats. Each broker is told where the controllers are through configuration, and it keeps its own copy of the log on local disk. Controllers should sit on their own listener, reachable only by brokers and administrators.

i
Controllers are light on data, heavy on care

Controller nodes store only the metadata log, which is small compared with message data. They need reliable disks and network, low latency between each other, and protection from noisy neighbours far more than they need large storage or many processors.

!
Spread controllers across failure domains

If all three controllers sit in the same rack or zone, one power event removes the majority. Place them in different racks or zones so a single incident cannot stop cluster decisions.

OThe Older Way: ZooKeeper and Pushed Updates

Understanding the old design makes the new one easier to appreciate. It also explains many older articles you may still read.

For most of Kafka’s history, cluster state was stored in an external system called ZooKeeper. The elected controller broker read that state, made decisions, wrote results back to ZooKeeper, and then pushed updates to every other broker over ordinary requests. Two request types were central. A LeaderAndIsr request told specific brokers that they had become leader or follower of certain partitions. An UpdateMetadata request told every broker the new facts about leaders, replicas and live brokers, and each broker stored them in its metadata cache.

1

A broker fails

Its session with ZooKeeper expires. The controller broker sees that the broker has disappeared.

2

The controller chooses new leaders

For each partition that the failed broker led, it picks a new leader from the in-sync replicas and writes that choice to ZooKeeper.

3

It tells the affected brokers

LeaderAndIsr requests go to the brokers holding the replicas so they can switch roles.

4

It tells everyone

An UpdateMetadata request goes to every broker so that all metadata caches learn the new leaders.

Why this design hit limits

What worked

  • Simple to reason about: one controller pushing to all
  • Battle-tested for years across many companies
  • Brokers held a complete cache for fast local answers

What hurt at scale

  • Two systems to run, secure and monitor
  • A new controller had to reload all state from ZooKeeper, which grew slow with many partitions
  • Pushed updates could reach brokers at different times or be missed
  • Partition counts were limited in practice

When a controller failed, the replacement had to read the state of every topic and partition before it could work. With very large clusters this could take a long time, during which no leader changes were possible. This was a major reason the Kafka community designed a new approach, described in the next chapter. Recent Kafka releases, starting with version 4.0, no longer support ZooKeeper at all.

i
Reading older material

If a blog post mentions UpdateMetadata requests, controller broker election through ZooKeeper, or ZooKeeper paths, it describes the older mode. The concepts of leaders, epochs and client caching still apply. What changed is how the broker cache gets its updates.

NThe Modern Way: The Metadata Log in KRaft

In modern Kafka, the cluster’s state is itself a Kafka-style log, and brokers keep their cache up to date by reading it, much as a consumer reads a topic.

In KRaft mode, all cluster decisions are stored as records in a special single-partition log, often called the metadata log (its internal topic name is __cluster_metadata). The active controller appends each decision to this log, and the controller quorum replicates it using a Raft-style consensus protocol so that a majority of controllers hold every record before it counts as committed. Brokers are not part of the voting group, but they read the log as followers, using the same fetch mechanism that replicas use.

Everyday analogy

Instead of the operations centre phoning each terminal, it now writes every announcement into a numbered notebook that all terminals can read. Each terminal keeps reading forward from where it stopped and updates its own screen. If a terminal is switched off for an hour, it simply catches up on the pages it missed.

What the records look like

Each record in the log describes one small change. Examples include a broker registering itself, a topic being created, a partition being added, a leader or ISR changing, a configuration value being set, an access rule being added, and a feature level being raised. Since each record is a tiny, self-contained fact, a broker can apply them one by one and always know exactly which version of the cluster picture it has reached, because every record has a position number, its offset.

Membership

Broker registrations

Brokers announce themselves and their listener addresses, and the controller records which are alive or fenced.

Topics

Topic and partition records

Creation, deletion and changes to partitions, replicas, leaders and the ISR are all recorded as small events.

Settings

Configuration records

Topic and broker level dynamic settings are stored in the same log, so they reach every broker in order.

Security

ACLs and credentials

Access rules and certain credentials are also stored, so every broker can check permissions from its own copy.

Images and deltas: how the cache is built

A broker turns the stream of records into its cache in two steps. First, it keeps an immutable snapshot of the full cluster picture, known as the metadata image. Immutable means it is never edited in place. Second, when a batch of new records arrives, the broker builds a delta that describes what changed, applies it to produce a brand-new image, and then swaps the new image in for the old one. Threads that were reading the old image keep working with it safely until they finish. Because unchanged parts are shared between old and new images rather than copied, this is cheap even for very large clusters.

Log
the ordered record of every cluster decision
Image
a frozen picture of the cluster at one log position
Delta
the small change that turns one image into the next
i
Why immutable images help

Request handler threads read the cache constantly. If the cache were edited in place, readers would need locks and could see half-finished changes. With swapped immutable images, a reader always sees one consistent snapshot, and the update never blocks anyone.

MMoving From ZooKeeper: What Happens to the Caches

Many organisations ran ZooKeeper-based clusters for years. Moving them to the log-based design changes how the broker caches are filled, though not what clients see.

Because modern releases no longer support ZooKeeper, a cluster that began life in the older mode must be migrated before it can move to the newest versions. Kafka provides a migration path that lets operators do this in stages, without taking the cluster offline. Understanding what each stage does to the metadata caches makes the process less mysterious.

1

Add the new controllers

A quorum of controller nodes is started alongside the existing cluster. It is told to expect a migration and to read the existing state from ZooKeeper.

2

Copy the state into the metadata log

The new controllers read topics, partitions, configs and access rules from ZooKeeper and write them as records into their own log. The metadata picture now exists in both places.

3

Brokers are restarted in the new mode, one by one

Each broker is restarted with settings that make it read the metadata log instead of waiting for pushed updates. On restart it loads the log, builds its image and registers with the new controllers.

4

Cut over to the new controllers

Once all brokers are ready, the new controllers become the only authority, and ZooKeeper is no longer used for decisions.

5

Remove ZooKeeper

After a period of confidence, the old coordination service is shut down and its settings deleted.

What clients notice

Very little. Clients use the same Metadata request before, during and after the move. Rolling restarts of brokers cause the usual short waves of leader changes and client refreshes, so the migration should be done at a quiet time with the same care as any rolling upgrade. The internal path by which brokers learn about changes is what differs: pushed requests before, a fetched log after.

Benefits after moving

  • One system to run and secure instead of two
  • Much faster controller failover
  • Room for many more partitions
  • Brokers that can catch up from snapshots

Things to plan for

  • Extra controller nodes to provision
  • A carefully ordered, staged procedure
  • Updating monitoring, which used ZooKeeper-era metrics
  • Checking that any tools reading ZooKeeper directly are replaced
!
Follow the official procedure for your version

The exact steps, supported version combinations and rollback points depend on the release you run. Treat the outline above as a map of the ideas, and use the official upgrade documentation for your version as the source of instructions.

HHow a Broker Fills and Catches Up Its Cache

A broker that starts up has an empty head. Before it can serve anyone, it must rebuild the picture of the whole cluster, and it must prove to the controller that it has done so.

When a KRaft broker starts, it does not ask the controller for a giant dump of state. It relies on two things it keeps on its own disk: a recent snapshot of the cluster picture and the tail of the metadata log after that snapshot. It loads the snapshot, replays the log records that came after it, and ends up with an image that is close to current. Then it connects to the active controller, registers itself, and continues fetching new records to close any remaining gap.

Snapshots keep the log short

The metadata log would grow forever if every record were kept. To prevent this, Kafka periodically writes a snapshot: a compact file holding the whole cluster picture as of a certain log position. Once a snapshot exists, older log records can be discarded. By default a new snapshot is taken after a sizeable amount of new records has been added, or after a long time interval, whichever comes first. A broker that has been offline so long that the records it needs are gone can simply download the latest snapshot from the controller and continue from there.

Everyday analogy

A terminal that was closed for a month does not need to read every announcement of that month. It picks up a printed summary of today’s full departure schedule, then reads only the announcements made since that summary was printed.

Fenced until ready

A broker that has not caught up must not receive client traffic, because its cache would give wrong answers. Kafka handles this with a state called fenced. A new or lagging broker registers as fenced. The controller keeps it fenced until the broker reports that it has read the log at least as far as its own registration record. Only then is the broker unfenced and eligible to lead partitions and to appear in metadata answers.

stateDiagram-v2
  [*] --> Starting
  Starting --> Fenced : loads snapshot and registers
  Fenced --> Active : caught up with the metadata log
  Active --> Fenced : misses heartbeats
  Active --> ShuttingDown : controlled shutdown
  ShuttingDown --> [*]
Figure 2: a broker becomes active only after its metadata cache has caught up, and it is fenced again if it stops reporting in.

Heartbeats tie the cache to liveness

An active broker sends a regular heartbeat to the controller. By default this happens every couple of seconds, and if the controller hears nothing for several heartbeats, roughly nine seconds by default, it fences the broker and moves its partition leadership elsewhere. Each heartbeat reply also tells the broker whether it is still allowed to serve. In this way, having a fresh cache and being alive are joined together: a broker that cannot keep its cache current, or cannot talk to the controller, drops out of service rather than giving stale answers.

!
Slow apply is a warning sign

If a broker takes a long time to apply metadata records, because its disk is slow or its CPU is starved, it can lag behind the log. It will then answer client questions with older facts and may eventually be fenced. Watching how far each broker’s applied position trails the log is one of the best health checks for the whole system.

IInside the Broker: From Log Records to Live Behaviour

A new image in memory is only useful if the parts of the broker that need it actually notice. Here is how a change spreads through the inside of a single broker.

Inside each KRaft broker, a component reads batches of records from the metadata log as they arrive. For every batch, it collects the changes into a delta and builds a new image from the previous one plus the delta. That new image is then handed to several listeners, sometimes called publishers, each responsible for one part of the broker’s behaviour. Every listener looks at the delta and acts only on what concerns it.

Replication

The replica manager

Sees that it has become leader or follower of a partition, creates or removes log folders, starts or stops fetchers, and follows the new leader when told to.

Groups

Group and transaction coordinators

Notice when the internal topics that hold consumer group and transaction state gain or lose leaders here, and load or unload that state.

Settings

Dynamic configuration handling

Applies changed broker and topic settings, for example a new retention time, without a restart.

Limits

Quota management

Picks up changed traffic limits for users and clients and applies them to live connections.

Access

The authorizer

Receives new and removed access rules and keeps its in-memory permission tables current.

Answers

The request layer

Reads the newest image when building Metadata responses and when validating each produce or fetch request.

Everyday analogy

When an announcement comes in at the terminal, several staff members hear it at once. The gate agent updates the gate sign, security adjusts the queue, the baggage team redirects trolleys, and the display board changes. Each acts on the part that concerns them, and none waits for the others.

Ordering inside the broker

Changes are applied in log order, and a new image only becomes visible after its delta has been fully applied. A request handler thread therefore never sees half of a change. Consider a leader change: the partition’s entry in the image gains its new leader and epoch in one step, not first the leader and then the epoch. This all-at-once switch is exactly what the immutable image design provides.

When something goes wrong while applying

Occasionally, applying a record fails, for instance because of a full disk when creating a partition folder. A failure in one listener does not stop the image from being updated for the others, and the failure is counted in error metrics so operators can see it. Serious failures make the broker shut itself down rather than continue with a cache that does not match reality, which is safer than serving wrong answers indefinitely.

i
Why this is worth knowing

Many mysterious symptoms turn out to be one listener not keeping up: a partition folder not created, a setting not applied, an access rule not yet active. Knowing that these are separate consumers of the same delta helps you look in the right place.

TThe Life of a Metadata Change: Creating a Topic

Let us follow one small change all the way from a request to every broker’s memory.

An engineer asks for a new topic named orders with 6 partitions and 3 replicas each. This is a typical metadata change, and it touches every stage we have discussed.

sequenceDiagram
  participant A as Admin client
  participant B as Any broker
  participant C as Active controller
  participant O as Other brokers
  A->>B: Create topic orders
  B->>C: Forward the request
  C->>C: Validate and choose replicas and leaders
  Note over C: Append topic and partition records to the metadata log
  C-->>B: Topic created
  B-->>A: Success
  C-->>O: Brokers fetch the new records
  Note over O: Each broker updates its local cache
Figure 3: a topic creation request travels to the active controller, becomes log records, and then reaches each broker’s cache.
1

The admin request reaches any broker

The client contacts whichever broker it knows. That broker does not decide anything itself. It forwards the request to the active controller.

2

The controller validates

It checks the topic name, that enough brokers exist for 3 replicas, that the requester is allowed to create topics, and that no topic named orders already exists.

3

It places the replicas

The controller picks brokers for each partition’s replicas, spreading them across brokers and racks, and picks a preferred leader for each.

4

It writes records to the metadata log

A topic record and six partition records are appended and replicated to a majority of the controller quorum. Once committed, the decision is permanent.

5

Brokers fetch and apply the records

Each broker’s next fetch returns the new records. It builds a delta, produces a new image and swaps it in. The broker now knows that orders exists.

6

Chosen brokers create the partitions

Brokers named as replicas notice the new partitions in the delta and create the log folders. Leaders start serving, and followers start fetching.

7

Clients discover the topic

The next time a producer asks any broker about orders, the answer comes from that broker’s freshly updated cache.

Why the small delay in step 5 is normal

Between the controller committing the change and the last broker applying it, there is a short window, typically a small fraction of a second in a healthy cluster. During it, one broker may already know about orders while another has not heard yet. A client that asks the slower broker gets “unknown topic”. It retries, and the second attempt succeeds. This is the price of caching, and it is why clients are built to retry metadata questions.

LThe Life of a Leader Change

Topic creation is calm. A leader change during a failure is the moment when the metadata cache matters most, and when stale copies do the most damage.

flowchart TD
  A["Leader broker stops"] --> B["Controller notices missed heartbeats"]
  B --> C["Controller writes a partition change record"]
  C --> D["Brokers fetch and apply the record"]
  D --> E["New leader starts serving, others follow it"]
  E --> F["Clients get errors then refresh metadata"]
  F --> G["Clients send traffic to the new leader"]
Figure 4: after a leader failure, the change flows from the controller to broker caches, and then to clients.

Suppose Broker 2 leads partition 3 of the orders topic, and it crashes. The controller stops hearing its heartbeats. After the session limit passes, it fences Broker 2 and looks at every partition that Broker 2 led. For partition 3 it picks a new leader from the in-sync replicas, say Broker 1, increases the partition’s leader epoch (a counter of leader changes), and writes a partition change record to the metadata log.

Every broker fetches the record and updates its cache. Broker 1 sees that it is now the leader and begins accepting writes. The other replicas see who the new leader is and start following it. Meanwhile, the producers and consumers that were using Broker 2 discover the problem the hard way: their connections fail or their requests to the wrong broker are refused. They then ask any live broker for fresh metadata and learn that Broker 1 leads partition 3.

TimeWhat the controller knowsWhat brokers knowWhat a client knows
Before the crashBroker 2 leads, epoch 7Broker 2 leads, epoch 7Broker 2 leads, epoch 7
Just after the crashBroker 2 leads (not yet noticed)Broker 2 leadsBroker 2 leads, connection fails
Controller reactsBroker 1 leads, epoch 8Still epoch 7 until records arriveBroker 2 leads, retrying
Brokers apply the recordBroker 1 leads, epoch 8Broker 1 leads, epoch 8Refreshing metadata
Client refreshedBroker 1 leads, epoch 8Broker 1 leads, epoch 8Broker 1 leads, epoch 8
Everyday analogy

A gate is closed because of a fault and the flight moves to a new gate. The operations centre announces it, the boards update within moments, and passengers who already headed to the old gate are redirected by staff. Those with the new gate printed on their boarding pass are already on the way.

i
Three delays add up

The failure-to-recovery time is roughly the time to detect the failure, plus the time for the controller to decide and commit, plus the time for brokers to apply the record, plus the time for clients to notice and refresh. Each stage has settings you can tune, and we will meet them in the chapters ahead.

UWhat a Broker Does With Its Cache

The cache is not just something brokers hold. It is consulted at nearly every step of handling a request.

Answering

Metadata requests

A client asks about some topics or all topics. The broker builds the answer purely from its cache: brokers, partitions, leaders, epochs, replicas and ISR. No call to the controller is needed.

Validating

Produce and fetch checks

On each produce request, the broker checks it is the leader for that partition and that the client’s view of the leader epoch is not out of date. A wrong broker refuses, with a clear error.

Authorizing

Permission checks

Access rules are held in the cache too, so deciding whether a client may write to a topic is a memory lookup, not a network call.

Limiting

Quotas and configs

Traffic limits and per-topic settings such as maximum message size come from the same cached picture, and take effect as soon as the updated record is applied.

Coordinating

Finding coordinators

Consumer groups and transactions have a coordinator broker chosen by hashing into an internal topic. Locating it uses the cached partition and leader information for that topic.

Replicating

Follower behaviour

Followers use the cached leader information to know whom to fetch from, and switch when the cache shows a new leader.

What a metadata answer contains

A response to a Metadata request lists the live brokers with their addresses, then for each requested topic it lists every partition together with the id of its leader, the leader epoch, the replica list, the in-sync replica list, and any replicas that are offline. The cluster identifier is included as well. Since the response is built directly from the broker’s own image, it always reflects exactly what that broker knew at that moment, no more and no less.

Field in the answerPurpose for the client
Broker id, host and portWhere to open connections
Partition count per topicNeeded to hash keys to partitions consistently
Leader id per partitionWhere to send produce and fetch requests
Leader epoch per partitionLets the client tell fresh answers from stale ones
Replica and ISR listsUsed by tools, and by consumers reading from nearby replicas
Offline replicasShows which copies are currently unavailable
i
Any broker will do

Because every broker keeps the full cluster picture, a client may ask any of them. That is why the bootstrap list in a client configuration only needs a few addresses. The client learns the rest of the cluster from the first answer it gets.

FFollowing One Produce Request Through Both Caches

To tie everything together, let us watch a single message from the moment a brand-new application starts, and see which cache is used at each step.

An order service starts up for the first time. It has never heard of the cluster, apart from three bootstrap addresses in its configuration. It is about to send its first message to the orders topic.

1

Cold start: the client cache is empty

The producer knows only the bootstrap addresses. It cannot pick a partition or a leader, since it has no partition count and no leader information.

2

It asks a bootstrap broker for metadata

The broker answers from its metadata image with the broker list, and for orders, its twelve partitions with leaders, epochs and replicas.

3

The producer fills its own cache

It stores the answer with a timestamp. It now knows the partition count and where each leader lives, and can open connections to the right brokers.

4

It chooses a partition

For a message with a key, it hashes the key and uses the partition count from its cache to select one. The choice is purely local, with no network call.

5

It sends the batch to the leader

The request carries the partition and the leader epoch from the client’s cache.

6

The broker checks its own image

It verifies it is the leader, that the epoch matches, that the topic exists, and that this client is allowed to write. All four checks read the same in-memory image.

7

The message is appended and acknowledged

The metadata is no longer involved. The rest is the replication story: appending to the log and waiting for followers.

StepWhich cache is readNetwork call needed?
Deciding the partitionClient cache (partition count)No
Finding the leaderClient cache (leader and epoch)No, after the first fill
Checking leadership and epochBroker imageNo
Checking permissionBroker image (access rules)No
Applying quotas and topic settingsBroker image (configs and quotas)No
Refreshing after an error or timeoutAny broker’s image, through a new Metadata requestYes, but rarely

Counting the network calls

For the first message, the producer makes one extra call to fetch metadata. For the next million messages to the same topic, it makes none, apart from an occasional timed refresh. That is the entire payoff of the two-layer cache: an expensive question asked once and then answered from memory, millions of times, on both sides of the connection.

SThe Second Cache: Inside Producers and Consumers

Clients do not ask a broker about metadata for every message. They keep a private copy and refresh it on a schedule and whenever something goes wrong.

flowchart TD
  S["Client needs the leader of a partition"] --> Q{"Is it in the local cache and still fresh?"}
  Q -->|"Yes"| U["Use it right away"]
  Q -->|"No, or an error occurred"| R["Send a Metadata request to any known broker"]
  R --> V["Update the local cache"]
  V --> T["Retry the original action"]
Figure 5: a client uses its own cache first and asks a broker only when the data is missing, old, or proved wrong.

When a producer sends its first message to a topic, it does not yet know the partitions or leaders. It sends a Metadata request to a bootstrap broker, stores the answer, and sends the message to the correct leader. All later messages to that topic use the stored answer, at no extra network cost. Consumers do the same, and also use the answer to find the coordinator for their consumer group.

The knobs that control freshness

SettingMeaningDefault
metadata.max.age.msRefresh the cache at least this often, even if nothing seems wrong5 minutes
metadata.max.idle.ms (producer)Forget a topic from the cache after it has not been used for this long5 minutes
max.block.ms (producer)How long a send may wait for metadata before failing60 seconds
retry.backoff.msPause before retrying after a failure, so clients do not hammer brokers100 ms
bootstrap.serversAddresses used to find the cluster the first timeNone, must be set

What triggers an early refresh

Timer

The cache grows old

After the maximum age passes, the next operation triggers a refresh even if all seems well. This is a safety net against missed changes.

Error

A broker says “not me”

Errors such as not-leader or unknown-topic-or-partition tell the client its copy is wrong. It refreshes at once, with a short backoff.

Network

A connection fails

If the broker a client was talking to disappears, the client marks its metadata as suspect and refreshes through a different broker.

New topic

An unknown topic is used

The first send to a topic not in the cache triggers a fetch of that topic’s metadata, and the send waits for it.

Everyday analogy

A passenger writes the gate on their boarding pass and walks straight there. They only look at a departure board again if an announcement is made, if the gate turns out to be wrong, or if it has been a long time since they last checked. Constantly re-checking the board would waste everyone’s time.

!
A subtle side effect on keyed messages

A producer decides the partition for a keyed message by hashing the key and taking it modulo the partition count. The count comes from the client’s cached metadata. If partitions are added to a topic, producers keep using the old count until they refresh, and the same key can land in a different partition afterwards. Order for that key across the change is not preserved.

GConsumer Groups, Coordinators and Metadata

Consumers use metadata for more than finding partition leaders. Their teamwork, called a consumer group, depends on it too.

Several consumers can share the work of reading a topic by joining a consumer group. Kafka spreads the topic’s partitions among the members so that each partition is read by exactly one member of the group at a time. A special broker, the group coordinator, keeps track of who is in the group, receives their heartbeats, and starts a rebalance whenever the membership or the list of partitions changes.

Finding the coordinator

Which broker is the coordinator for a given group? Kafka answers with a simple rule. The group name is hashed to pick one partition of an internal topic that stores group progress. The broker that leads that partition is the coordinator for that group. A consumer sends a find-coordinator request to any broker, and the broker works out the answer using its metadata image: the partition count of the internal topic and the current leader of the chosen partition.

Everyday analogy

A large event has many registration desks. Your surname decides which desk handles you, and which staff member is on that desk today is written on the board. If the staff member changes, the board changes, and you are simply told to go to the new person the next time you visit.

1

The consumer starts and asks any broker for the coordinator

The broker hashes the group name to an internal partition and looks up its leader in the cached metadata.

2

The consumer joins the group

It connects to the coordinator and announces which topics it wants to read.

3

Partitions are assigned

An assignment is worked out using the partition lists of the subscribed topics, which come from cluster metadata. Every member receives its share.

4

Consumers fetch from the partition leaders

Each member finds its partitions’ leaders through its own cached metadata, and starts reading.

5

Heartbeats continue

Members send regular heartbeats. If one stops, the coordinator removes it and starts a rebalance.

When metadata changes cause rebalances

Trigger

Partitions are added to a topic

The consumers’ cached metadata eventually shows the new partitions. The group must reassign so that someone reads them.

Trigger

A new topic matches a pattern

A group subscribed by a regular expression notices the new topic at its next metadata refresh and rebalances to include it.

Trigger

The coordinator moves

If the leader of the internal partition changes, consumers receive a not-coordinator error, look up the new coordinator through metadata, and reconnect.

Trigger

A member leaves or joins

Deployments and crashes change membership. Not a metadata change, but the reassignment then reads fresh cluster metadata.

Newer group protocols

Recent Kafka versions include a newer consumer group protocol in which the coordinator broker computes assignments on the server side, instead of one client doing it. With that design, the broker relies on its own cached view of topics and partitions when deciding who gets what, and changes in metadata reach the group through the broker’s normal updates rather than through each client’s refresh timer. The core idea stays the same: assignment is only as good as the metadata behind it.

i
Transactions follow the same shape

The transaction coordinator is found in a similar way, by hashing the transactional id onto a partition of an internal topic and looking up its leader in the metadata. The lesson is general: whenever Kafka needs to name “the broker responsible for X”, it turns X into a partition and asks the metadata who leads it.

!
Rebalances are expensive, so avoid triggering them by accident

Frequent rebalances pause consumption while partitions are reassigned. Sources include short session timeouts, slow processing that misses the poll deadline, broad regex subscriptions on busy clusters, and repeated coordinator moves. Stable metadata makes for stable groups.

ELeader Epochs: Telling Fresh Metadata From Stale

Two copies of the metadata can disagree. Leader epochs give Kafka a simple way to decide which one is newer.

A leader epoch is a number attached to each partition that increases by one every time leadership changes. Every metadata answer includes it, and every produce or fetch request from a modern client includes the epoch the client believes is current. This small number solves two problems at once.

Problem 1

A client has old metadata

It sends a request stamped with epoch 7 to a broker that knows epoch 8 is current. The broker can see immediately that the client is behind and reply with a specific error, so the client knows to refresh.

Problem 2

A broker has old metadata

A client holding epoch 8 asks a broker that has only seen epoch 7. The broker can tell it is behind and reply that it does not yet know the epoch, so the client tries again shortly instead of trusting it.

sequenceDiagram
  participant P as Producer with an old cache
  participant Old as Former leader
  participant New as New leader
  P->>Old: Produce to partition 3, leader epoch 7
  Old-->>P: Not the leader, newer leader information attached
  P->>New: Produce again with leader epoch 8
  New-->>P: Success
  Note over P: The client cache now says epoch 8
Figure 6: a stale client is corrected by the broker it wrongly contacted, and moves on to the new leader.

Ignoring answers that are older than what we have

Clients use epochs in one more way. When a Metadata response arrives, the client compares each partition’s epoch with the one it already stored. If the new answer carries a lower epoch, it came from a broker that is lagging behind, and the client keeps its own newer information instead of going backwards. Without this rule, a client that happened to ask a slow broker could replace a correct cache with an outdated one.

Newer Kafka versions go a step further. When a broker refuses a produce or fetch request because it is not the leader, it can attach the identity and epoch of the leader it knows about within the error response. The client can then use that immediately without a separate Metadata round trip, which shortens recovery after a leader change.

i
The same idea, in replication

Leader epochs also protect replication, where followers use them to decide how far to truncate their logs after a leader change. Whether the subject is metadata or data, the epoch is the same tool: a simple counter that lets any two parties agree on which view of the world is newer.

CStaleness, Consistency and the Errors You Will See

Cached metadata is eventually consistent. Copies may briefly differ, but they always converge. Kafka expresses each kind of disagreement as a specific error code.

Eventual consistency sounds abstract until you see the errors it produces. Every error below is a normal part of life on a busy cluster. A handful per minute during a change is expected. A constant stream is a sign that something needs attention.

ErrorPlain meaningUsual causeWhat the client does
NOT_LEADER_OR_FOLLOWERThis broker is not the leader for that partitionLeader moved and the client cache is oldRefresh metadata and retry
UNKNOWN_TOPIC_OR_PARTITIONThis broker does not know that topic or partitionVery new topic not yet applied, or a typo, or deletionRetry briefly, then fail if it persists
LEADER_NOT_AVAILABLEA leader is being elected right nowBroker failure or new topic being set upWait a short time and retry
FENCED_LEADER_EPOCHThe request carries an epoch older than the broker knowsClient cache is behindRefresh metadata and retry
UNKNOWN_LEADER_EPOCHThe request carries an epoch newer than the broker knowsBroker cache is behindRetry after a short delay
TOPIC_AUTHORIZATION_FAILEDClient is not allowed to see or use that topicMissing access ruleFail, since retries will not help

The client-side timeout

The most common metadata problem in application logs is a producer failing with a message that the topic was not present in the metadata after a set time, typically 60 seconds. It means the producer asked for metadata, waited up to its blocking limit, and never received a usable answer for that topic. Typical causes are a wrong topic name with auto-creation disabled, a lack of permission to describe the topic, a bootstrap address that leads nowhere, or an entire cluster being unreachable.

1

Check the address

Confirm that at least one bootstrap address works from where the client is running, including DNS names and firewalls.

2

Check the topic

Confirm the topic exists, its name has no typo, and it has partitions with leaders.

3

Check permissions

A client that lacks permission to describe a topic is told it does not exist or is not authorized, so review access rules.

4

Check the returned addresses

Even when the bootstrap works, the metadata may return addresses the client cannot reach. That leads to the topic of the next chapter.

i
Retry, don’t panic

Errors that start with “not leader”, “unknown epoch” or “leader not available” are meant to be retried, and Kafka clients do so automatically. Design your application to allow enough time for retries during a leader change, rather than failing at the first sign of one.

AAdvertised Listeners: The Addresses Inside the Metadata

Metadata does not only say who leads a partition. It also says how to reach that leader. When the addresses are wrong, everything looks fine at first and then fails.

A broker may be reachable on several networks at once: a private network for other brokers, an internal network for applications in the same data centre, and a public address for outside clients. Kafka models each as a named listener. The setting called listeners tells the broker which addresses and ports to open. The setting called advertised.listeners tells the broker which addresses to announce to clients through the metadata, and these can be different.

Everyday analogy

A shop has a back door for deliveries and a front door for customers. The shop’s public sign must list the front door address. If it lists the back door, or a street name only staff understand, customers arrive at the wrong place even though the shop is open and the sign looks official.

How the connection flows

1

Client connects to a bootstrap address

This is the address written in the client’s configuration. Only this first step uses it.

2

The broker answers from its cache

It returns the broker list with the address for the listener on which the client connected, taken from the advertised settings.

3

The client connects to the leaders directly

For each partition it uses, the client opens a connection to the address in the metadata, which may be a different broker from the bootstrap one.

4

Traffic flows, or fails

If the advertised address is not reachable from the client, the data step times out even though the bootstrap step worked.

The classic mistake

A team moves Kafka from a laptop to a cloud server. The bootstrap address is the server’s public name, so the client connects and receives metadata. But the broker still advertises its internal machine name, which only makes sense inside the cloud network. The client sees the leader’s address, cannot resolve or reach it, and every send times out. The broker is healthy and the topic exists, yet nothing flows, because the map the client was given points to an address it cannot use.

SymptomLikely causeFix
Connects to bootstrap, then times out on sendAdvertised address unreachable from the clientAdvertise an address the client can reach
Works inside the network, fails from outsideOnly an internal listener is advertisedAdd an external listener with its own advertised address
Client cannot resolve the hostnameAdvertised name is not in the client’s DNSUse names that resolve for that client
Listener not found errorClient connected on a listener the broker does not advertiseCheck listener names and security protocol mapping
!
Bootstrap working proves little

A successful first connection only proves the bootstrap address works. Always test that the addresses returned inside the metadata are also reachable from the client’s network.

TAuto Topic Creation and Metadata Requests

A Metadata request can do more than ask. Under some settings, asking about a topic that does not exist makes Kafka create it.

Brokers have a setting called auto.create.topics.enable. When it is on, a client that asks for metadata about an unknown topic, or sends a message to one, can cause that topic to be created with default settings. The Metadata request carries a flag saying whether the client allows this. Clients can turn it off with their own setting, so that an accidental typo does not create a stray topic.

Why teams like it

  • Convenient in development and testing
  • No separate setup step for new topics
  • Applications can start before an operator prepares the topic

Why production teams avoid it

  • A typo silently creates a wrong topic with default partitions
  • Defaults may not suit the workload
  • Any client with basic access can create topics
  • Metadata questions have side effects, which is surprising

What happens behind the scenes

When a broker receives a Metadata request for an unknown topic with auto-creation allowed, it does not create the topic itself. It forwards a creation request to the active controller, just like an administrator’s request, following the steps in Chapter 12. The first answer to the client is usually “leader not available”, because the topic’s partitions do not have leaders yet. The client retries after its backoff, and soon receives real metadata. This explains a familiar pattern in logs: one warning about leader not available on the very first send to a new topic, followed by normal operation.

i
A safer production pattern

Turn auto-creation off on the brokers, create topics deliberately with the intended partition count, replication factor and settings, and keep those definitions in version control. It removes a whole class of surprises and keeps the metadata tidy.

The cost of a typo

A service writes to a topic named payments-events but a configuration file says paymnets-events. With auto-creation on, Kafka happily creates the misspelt topic with default settings. Events pile up unread, and nothing fails. With auto-creation off, the first send fails loudly with a metadata timeout, and the mistake is caught within minutes.

FFour Failure Stories With Real Numbers

The best way to feel how the metadata cache behaves is to watch it under pressure. These four stories use plausible numbers to show the mechanics.

Story 1: the reconnection storm

A cluster of six brokers serves 20,000 client connections across many applications. Broker 4 crashes, and it led about 500 partitions. The controller notices after the heartbeat limit of roughly nine seconds, moves the leaders and records the changes. Within a second or two, all brokers have applied the change. But in the meantime, thousands of clients with connections to Broker 4 saw errors and each sent a Metadata request to a surviving broker.

Here the design pays off. Every broker answers from memory, so the flood is spread over five machines and handled quickly. Clients also wait a short backoff before retrying, so their requests do not all arrive in the same instant. Most applications recover in a few seconds beyond the detection time. If clients had no backoff, or if every metadata answer required a call to the controller, the same event could turn into a second, self-made outage.

i
What to learn

Most of the recovery time is detection time. Tuning heartbeat and session settings trades speed against false alarms. Too aggressive, and a brief pause fences a healthy broker.

Story 2: the broker that fell behind

Broker 2 shares a disk with a noisy neighbour, and its disk stalls for twenty seconds. During that time, the controller commits a leader change for a partition that Broker 2 used to lead. Broker 2 cannot apply the record yet, so for a while its cache still says it is the leader. A producer with an old cache sends it a message with the old epoch. Broker 2 has not yet learned the new epoch, so it cannot yet reject the message on epoch grounds alone.

What saves the day is layered protection. First, Broker 2 has stopped sending heartbeats normally, so the controller fences it and moves leadership away. Second, when Broker 2 does catch up and applies the record, it stops accepting writes for that partition. Third, replicas follow the new leader, so an old leader’s late writes cannot be committed by the in-sync replicas. The metadata cache is one line of defence, and the epoch checks in the replication protocol are another.

Story 3: doubling the partitions

An orders topic has 6 partitions and the team needs more throughput, so they raise it to 12. The controller commits the change instantly and all brokers apply it within a second. But producers still hold cached metadata that says 6 partitions, and they keep hashing keys modulo 6 until their next refresh, which can take up to the maximum metadata age of five minutes by default.

Once each producer refreshes, it starts hashing modulo 12, and a customer whose orders used to go to partition 2 may now go to partition 8. Consumers reading partition 2 have older messages for that customer, and consumers of partition 8 have newer ones. Order across the boundary is lost. Consumers subscribed by pattern also notice new partitions only at their own refresh interval. The lesson is to plan partition counts up front, and to treat an increase as an event that can break per-key ordering.

Story 4: the controller failover

The active controller crashes. The remaining controllers hold an election, and one of them becomes active, typically within a few seconds. During this window, no new decisions can be made. Nobody can create a topic, and if a broker fails during the window, its leaders cannot be moved until the new controller takes over.

Yet ordinary produce and consume traffic continues without any interruption, since brokers serve requests from their cached metadata and do not need the controller for the data path. When the new active controller comes up, brokers reconnect to it and continue fetching the log from where they stopped. Because the log is replicated to a majority before any decision counts, the new controller holds every committed decision, so nothing already announced is lost.

StoryWhat was staleUser-visible effectMain lesson
Reconnection stormClient caches pointing to a dead brokerSeconds of retriesCache answers plus backoff absorb storms
Lagging brokerOne broker’s cacheA few rejected or delayed requestsFencing and epochs protect correctness
Doubling partitionsClient partition countPer-key order breaks at the switchPlan partition counts early
Controller failoverNothing on the data pathBrief pause in administrative changesData path does not depend on the controller

PPerformance and Scalability of the Metadata Cache

The cache is fast because it lives in memory, but it is not free. Its cost grows with the size of the cluster and the behaviour of its clients.

Every partition of every topic has an entry in the cache: its leader, epoch, replica list and ISR. A cluster with a few thousand partitions has a trivial cache. A cluster with hundreds of thousands has one measured in tens or hundreds of megabytes, and every broker holds a full copy. That is still small next to the message data, but it is not nothing, and other costs grow with it.

1 copy
of the full cluster picture on every broker
Grows
with partitions, replicas and topics
In memory
so reads are fast and need no disk or network

The all-topics request

A Metadata request can name specific topics or ask for all of them. The second form is convenient and expensive. On a big cluster, the answer lists every partition of every topic. As a rough illustration, if each partition entry takes around a hundred bytes in the response, a cluster with 200,000 partitions would send about twenty megabytes for a single request. If hundreds of monitoring tools, dashboards or pattern-subscribed consumers make that request every few minutes, brokers spend much of their time building and sending enormous answers.

Client habit

Ask only for what you need

Producers request just the topics they write to. Applications that list all topics on every poll should be redesigned to cache the list.

Client habit

Avoid broad regex subscriptions

A consumer subscribed by pattern must fetch broad metadata regularly to spot new matches. Prefer explicit topic lists on large clusters.

Tooling

Slow the monitoring pollers

Dashboards and admin scripts that describe the whole cluster each second add load. Poll at a sensible interval, or read metrics instead.

Design

Keep partition counts sensible

More partitions bring more parallelism but also a larger cache, longer startup, bigger answers and more work per change.

Why the modern design scales better

The older push-based design had each metadata change sent from the controller to every broker, and a new controller had to reload everything from ZooKeeper. The modern log-based design changes both. Changes are small records that brokers pull, and a new active controller already holds the whole log in memory, since standby controllers apply it continuously. Also, applying a delta to an immutable image shares all unchanged parts, so a single change to one partition does not copy the entire cluster picture. One goal of the design was to allow clusters with a very large number of partitions, in the order of millions, with fast controller failover.

i
Refresh interval trade-off

A shorter metadata.max.age.ms means clients notice silent changes sooner but generate more metadata traffic. A longer one saves traffic but leaves stale data around longer if an error does not trigger an early refresh. The default of five minutes suits most systems, because errors already trigger prompt refreshes when it matters.

CConsistency and the Trade-offs Behind the Design

Kafka could have chosen a different way of sharing the cluster picture. Comparing the alternatives shows why this one was chosen, and what it costs.

ApproachHow it worksStrengthWeakness
Ask the controller every timeEach request triggers a lookup at one central serviceAlways up to dateBottleneck, slow, single point of failure
Broker cache from an ordered log (Kafka)Brokers apply the same records in the same orderFast, scalable, all brokers convergeBrief staleness is possible
Static configuration on clientsClients hard-code where everything livesNo lookups at allCannot react to failures or growth
Client-side only discoveryClients probe brokers to find leaders by trialNo cluster-wide stateWasted requests, slow recovery

Kafka’s choice gives strong ordering of changes but not instant delivery to every reader. All brokers apply the same records in the same order, so they never disagree about the sequence of events, only about how far along the sequence they have reached. Since a leader epoch accompanies every change, any request can be judged as fresh or stale, and mistakes are corrected without harm.

Everyday analogy

Boards showing the departure list are guaranteed to show the list in the right order, even if one board is a second slower than the others. Nobody ever sees gate 7 assigned before gate 6 was cleared, but somebody might briefly read yesterday’s gate for a flight that has just moved.

Where CAP shows up

When the network splits, a system must choose between staying consistent and staying available. For metadata, Kafka chooses consistency for decisions: changes need a majority of the controller quorum, so a minority partition cannot create topics or elect leaders. For reads, it favours availability: brokers keep answering from their last known cache during the split. The result is a cluster that will not make conflicting decisions but will continue serving the existing traffic.

What this design guarantees

  • All brokers see changes in the same order
  • No two active controllers make conflicting decisions
  • Reads continue during controller trouble
  • Stale requests are detected by epochs

What it does not guarantee

  • That every broker has the latest change at the same instant
  • That a client’s private cache is current
  • Administrative changes during a lost majority
  • Ordering of keys across a partition-count change

SSecurity Around Metadata

Metadata may look harmless, but a list of topics, partitions and addresses is exactly what an attacker wants to see first.

Topic names often reveal business activity: a topic called merger-negotiations or customer-refunds tells a story. Broker addresses reveal network layout. Access rules define who can do what. Because all of this sits in the metadata cache, it deserves protection just like the messages.

Visibility

Filtered answers

A broker only includes topics the caller is allowed to describe. Clients without permission are told the topic is not authorized or is unknown, not shown its details.

Identity

Authenticate before answering

Use TLS and a login method such as SASL or mutual certificates, so anonymous callers cannot request metadata from the cluster at all.

Isolation

Separate controller network

The controller quorum should be reachable only by brokers and administrators, on its own listener, never by ordinary applications.

Address hygiene

Advertise only what clients need

Do not expose internal hostnames or private topology through the advertised listeners of an externally reachable listener.

Permission checks come from the cache

In KRaft clusters, access rules are stored in the metadata log and every broker keeps them in memory. This makes checks very fast, but it also means a rule change reaches each broker when that broker applies the record. In the short window before that, a broker may still use the old rule. For most systems this is invisible, but for urgent revocations, such as removing a compromised account, it helps to verify that all brokers have applied the change, and to disable the credential at the identity source too.

!
Beware permissive defaults

Some authorizer settings allow everyone when no rule exists for a resource. On a shared cluster, such a setting means new topics are readable by anyone until rules are added. Prefer denying by default and granting deliberately.

MMonitoring the Metadata Cache

A healthy cache is one that is current, quiet and fast. A few metrics tell you whether it is all three.

MetricWhat it tells youWhat to do
Last applied metadata record offset and lagHow far this broker’s cache trails the logAlert on lag that keeps growing, since it means stale answers
Metadata load and apply error countsRecords the broker failed to processAny non-zero value needs investigation
Active controller countHow many controllers claim to be activeExactly one is healthy. Zero or two is an emergency
Fenced broker countBrokers currently held out of serviceAlert if it stays above zero after maintenance
Global topic and partition countsOverall size of the cluster pictureTrack growth to plan capacity
Metadata request rate and timeHow often clients ask and how long answers takeSpikes point to broad or badly behaved clients
Request errors by typeHow often clients hit not-leader or unknown-topic errorsBursts after changes are normal. Constant streams are not
Producer metadata ageHow old the producer’s cached metadata isValues far above the refresh interval suggest refresh is failing

A simple diagnosis path

1

Clients report not-leader errors

Check whether a leader change happened recently. A short burst that fades is normal. A steady stream is not.

2

Compare the brokers’ applied positions

Find out whether one broker’s metadata lag is much larger than the others. That broker is answering with old facts.

3

Inspect the slow broker

Look at its disk latency, CPU, garbage collection and network path to the controller. One of these is usually the cause.

4

Check the client side

If brokers agree with each other, examine client versions, bootstrap lists and advertised addresses, since the fault may be in the client’s private copy.

i
Metric names vary by version

Exact metric names and groupings change between Kafka releases. Confirm the current names in the documentation for your version, and build dashboards around the ideas above rather than a fixed list of names.

RReal-World Usage

Companies running Kafka at scale meet the metadata cache in daily life, mostly through its side effects.

LinkedIn: where the pressure began

Kafka was created at LinkedIn, which has publicly described running very large clusters with a huge number of partitions. Growth in partition counts is what made the older ZooKeeper-based design painful: slower controller failovers and heavier state to reload. The community’s work to move cluster state into Kafka’s own log, and to keep every broker’s cache current from it, grew directly out of the needs of operators at this size.

Uber: many clients, constant change

Uber has written publicly about running Kafka as a backbone for a large number of services, with thousands of applications producing and consuming. In an environment like that, deployments happen all day and clients start and stop constantly. Every start is a metadata request, and every broker maintenance is a wave of refreshes. Fast in-memory answers and client backoff are what keep such churn from turning into an overload.

Cloud-managed Kafka services

Managed Kafka offerings from cloud providers and vendors put brokers behind load balancers and private networks. Their most common support issue is exactly the advertised-listener problem from Chapter 20: the bootstrap address works, but the addresses returned in metadata are unreachable. Good documentation for these services spends a lot of space explaining which addresses to advertise for each network path.

An illustration: a retail platform on sale day

This is a simplified illustration, not a description of any specific company. A retailer runs a promotion that multiplies traffic by ten. Autoscaling starts three hundred new application instances in a few minutes. Each instance opens a producer, requests metadata for two topics, and starts sending. Because the brokers answer from memory and each client asks for only the topics it needs, the added load is trivial. In contrast, an old analytics tool that requests all topics every few seconds adds far more load than the three hundred new instances combined.

i
The pattern behind the stories

Metadata caching seldom causes headlines. When it does, the cause is almost always one of three things: addresses that clients cannot reach, clients that ask for far more than they need, or a broker that has fallen behind its log.

DDesign Patterns and Anti-patterns

A few habits keep the metadata path healthy. A few shortcuts quietly damage it.

Patterns that work

Pattern

Several bootstrap addresses

List at least two or three brokers, ideally in different racks or zones, so a client can start even if one broker is down. A load-balanced name in front of the brokers is also common.

Pattern

Named listeners per network

Give each network path its own listener and advertised address: internal, external, and so on. Each client then gets addresses it can reach.

Pattern

Request only needed topics

Keep metadata requests narrow so answers stay small, and cache lists of topics in tools instead of refetching them.

Pattern

Explicit topic creation

Create topics through reviewed scripts or infrastructure code, with the right partition count and settings from day one.

Pattern

Dedicated controllers on larger clusters

Run controller nodes separately from brokers when a cluster is big, so heavy data traffic cannot slow down decision making.

Pattern

Tolerant retry settings

Allow enough time and retries for a leader change to complete and be discovered, rather than failing at the first error.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What people do

They leave the advertised address as an internal machine name after moving Kafka to a new network.

Why it hurts

Clients connect to the bootstrap address, get metadata, and then fail to reach the advertised leaders. The problem looks like a broken broker or a network fault, and can take hours to diagnose.

Do this instead

Advertise addresses that each client group can actually reach, and test from each network with a real produce and consume, not only a connection check.

ANTI-PATTERN 02Avoid
What people do

They build monitoring tools that request the complete list of topics and partitions every second.

Why it hurts

Each request forces brokers to build and send the entire cluster picture. On a large cluster this wastes CPU and network and slows real traffic.

Do this instead

Poll at a relaxed interval, request only what is needed, or rely on metrics that brokers already publish.

ANTI-PATTERN 03Avoid
What people do

They increase a topic’s partition count casually on a topic where message order per key matters.

Why it hurts

Producers switch to the new count as they refresh their caches, so the same key begins to land on a different partition and per-key order breaks at that moment.

Do this instead

Choose partition counts with room to grow. When you must change them, plan for it: pause producers, drain consumers, or create a new topic and migrate.

ANTI-PATTERN 04Avoid
What people do

They hard-code a single broker as the only bootstrap server.

Why it hurts

If that one broker is down when a client starts, the client cannot find the cluster even though every other broker is healthy.

Do this instead

List several brokers, or a name that resolves to several of them, so the first step always has a working option.

BBest Practices and Common Mistakes

A short checklist for reviews and a table of mistakes that keep coming back.

1

Test the full path from every network

For each group of clients, verify that the bootstrap works and that the addresses inside the metadata are reachable, using a real send and receive.

2

Keep clients reasonably modern

Newer clients handle leader changes faster, use leader epochs and receive leader hints in error replies. Old clients need more refreshes to recover.

3

Treat topic creation as a deliberate act

Turn off automatic creation in production, and create topics with reviewed settings.

4

Watch the applied position of every broker

A broker that is up but behind its log is quietly serving old facts. Alert on lag, not only on liveness.

5

Restart brokers one at a time

Wait for the broker to be unfenced and caught up before moving to the next, so the cluster never loses too many good caches at once.

6

Rehearse failures

Stop a broker in a test cluster and watch client errors, refreshes and recovery time. Teams that have seen it once respond calmly in production.

Common mistakeWhat goes wrongBetter approach
Testing only the bootstrap connectionData path fails later on unreachable advertised addressesTest a real produce and consume from the client network
Assuming a new topic is instantly visible everywhereBrief unknown-topic errors right after creationAllow a short retry period after creating a topic
Setting a very long metadata age to cut trafficSilent changes noticed lateKeep the default unless measurements say otherwise
Setting a very short metadata ageNeedless request load on brokersRely on error-driven refreshes for urgent changes
Ignoring controller healthAdministrative changes stall unnoticedMonitor active controller count and quorum health
Auto-creating topics in productionTypos create stray topics with default settingsDisable it and create topics deliberately

MMyths, Traps and Gotchas

Some beliefs about metadata caching sound sensible and are wrong. Here are the most common.

Myth

“Clients ask the controller for metadata”

Clients ask any broker. Brokers answer from their own cache. Clients normally never talk to the controller directly.

Myth

“If the controller is down, Kafka is down”

Producing and consuming continue from cached metadata. What stops is administrative change and leader elections until a controller is active again.

Myth

“The bootstrap server is the only server used”

It is used just to discover the cluster. After that, clients talk directly to whichever brokers lead their partitions.

Myth

“All broker caches are identical at every moment”

They converge quickly, but at any instant one broker may be a few records behind another. That is normal and handled with epochs and retries.

Myth

“More frequent refresh is always safer”

Beyond a point it just adds load. Error-driven refreshes already cover urgent cases, and the timer is only a backstop.

Myth

“The metadata cache stores messages”

It holds descriptions of the cluster only. Message data lives in partition logs and, for speed, in the operating system’s page cache.

Myth

“Unknown topic always means the topic is missing”

It can also mean the broker has not yet applied a fresh creation record, or that the caller lacks permission to see the topic.

Myth

“Adding partitions is harmless”

It is safe for data, but changes how keys map to partitions once clients refresh, which can break per-key ordering.

Gotchas worth remembering

!
Old material describes old modes

Many articles, and many answers in old forums, describe ZooKeeper-era behaviour. Check that any advice about controllers, UpdateMetadata requests or ZooKeeper paths applies to the version you actually run.

!
Load balancers and metadata do not mix by default

A load balancer in front of brokers works for the bootstrap step, but the metadata still returns direct broker addresses. Unless every advertised address goes through the balancer too, clients will bypass it or fail.

!
Size matters more than you expect

The all-topics request that was harmless on a small cluster can become a serious load after a cluster grows a hundredfold. Revisit tools written years ago when the cluster was small.

PPutting It Together: Tuning for Three Scenarios

Let us apply what we have learned to three different workloads. The method matters more than the specific numbers.

Ask four questions for any system. How quickly must clients recover from a leader change? How many clients and partitions exist? Do clients connect from several networks? And how costly is a mistake in topic setup? The answers point to different choices for the metadata path.

Scenario (illustration)Main concernClient side choicesCluster side choices
Payments platform, moderate sizeFast, safe recovery and no stray topicsModern clients, generous retry time, several bootstrap brokersAuto-creation off, strict access rules, dedicated controllers
Large shared cluster, thousands of clientsMetadata load and noisy neighboursNarrow metadata requests, no broad patterns, default refresh intervalWatch request rates, cap partition growth, review tools that poll everything
Hybrid setup: apps in the cloud and on premisesReachable addresses for every networkEach client group uses its own listener and bootstrap nameSeparate listeners and advertised addresses per network
1

Map the networks

List every place clients run from, and decide which address each of them should receive in the metadata.

2

Estimate the size

Count topics, partitions and clients. Ask whether any tool requests all topics, and how often.

3

Set recovery expectations

Decide how long an application may spend retrying during a leader change, and set timeouts to match.

4

Lock down creation and access

Turn off automatic creation and review who can describe and create topics.

5

Rehearse and measure

Stop a broker, watch the errors and refreshes, and record how long recovery takes. Adjust from evidence, not guesses.

A quick sanity check for any design

Ask aloud: “If one broker disappears right now, how does each of my clients learn about the new leader, and how long will that take?” If the team can answer with specific settings and observed timings, the metadata path is understood. If the answer is “it should just work”, it is worth a rehearsal.

FFrequently Asked Questions

Short answers to questions that come up again and again.

Q1Does every broker really hold metadata for the entire cluster?
Yes. Each broker keeps a full copy of the cluster picture, including topics it does not host. This is what lets any broker answer any Metadata request and validate requests without asking anyone else.
Q2Do clients ever talk to the controller?
Normally not for data or metadata. Administrative requests from tools may be forwarded by a broker to the active controller, but producers and consumers deal only with brokers.
Q3How often do clients refresh their metadata?
At least every five minutes by default, and immediately when an error suggests the copy is wrong, when a connection fails, or when a new topic is used.
Q4What happens to producing if the active controller crashes?
Data traffic continues because brokers keep serving from cached metadata. Topic creation and leader elections pause until a new controller becomes active, usually within seconds.
Q5What is a fenced broker?
A broker that the controller is not allowing to serve because it is new, behind on the metadata log, or has missed heartbeats. It is unfenced after it catches up.
Q6Why do I see leader-not-available on the first send to a new topic?
The topic was just created, and its leaders were still being elected. The client retries after a short backoff and then succeeds.
Q7Why does my client connect but never send data?
Most often the addresses returned inside the metadata are unreachable from the client, usually because of the advertised listener settings. The bootstrap connection worked, but the leader connections cannot.
Q8Is the metadata cache the same as the page cache?
No. The metadata cache describes the cluster. The page cache is the operating system’s memory holding recent message data. They serve different purposes.
Q9Does removing ZooKeeper change how clients see metadata?
Clients use the same Metadata request as before. The change is inside the cluster, where brokers now build their cache from Kafka’s own metadata log instead of pushed updates.
Q10How can I tell that a broker’s cache is stale?
Compare its applied metadata position with the log, watch for rising epoch-related errors from clients, and check whether it is being fenced. A growing lag is the clearest sign.
Q11Can adding partitions break my application?
Not the data, but it can change which partition a given key maps to once producers refresh, which affects per-key ordering. Plan increases carefully.
Q12Should I shorten the refresh interval to recover faster?
Rarely. Errors already trigger prompt refreshes for the cases that matter. Shortening the timer mostly adds request load.

SSummary and Key Takeaways

A cache of the cluster’s map, kept in every broker and every client, is what lets Kafka answer “who leads this partition?” in microseconds.

The controller decides, the metadata log records, and each broker turns those records into an in-memory picture that it can read without locks or network calls. Clients copy the parts they need and refresh them on a timer, after errors, or when they meet something new. Leader epochs let every party tell fresh from stale, so the occasional disagreement is corrected quickly and safely. Understanding this chain explains both the speed of Kafka and the handful of surprises that come with it: unknown topics right after creation, unreachable advertised addresses, and keys that move when partitions grow.

Key Takeaways

  • Every broker holds the whole cluster picture: topics, partitions, leaders, epochs, replicas, configs and access rules, so any broker can answer any client.
  • The controller decides and the log records. In modern Kafka, brokers build their cache by reading a replicated metadata log, applying small deltas to immutable images.
  • Clients keep a second cache and refresh it on a timer, after errors, and on first use of a topic. Errors such as not-leader are normal signals, not disasters.
  • Leader epochs identify the newer view, so stale requests and stale answers are detected and corrected without harm.
  • A broker that falls behind is fenced, so a stale cache cannot serve clients for long. Watch each broker’s applied position, not just its liveness.
  • Advertised listeners are part of the metadata. If clients cannot reach the addresses returned, the bootstrap succeeds and the data path fails.
  • Keep requests narrow and settings deliberate: ask only for needed topics, create topics explicitly, plan partition counts, and rehearse failures.