Partition Count Impact on Latency in Kafka: When More Lanes Help and When They Hurt

Partition Count Impact on Latency in Kafka: When More Lanes Help and When They Hurt

A complete, plain-language guide to how the number of partitions changes producer batching, replication, consumer delivery, rebalances, failure recovery, and tail latency, with a practical method for choosing a partition count and measuring the result.

Imagine a highway that leads into a busy city. When traffic is heavy, adding lanes lets more cars move at once, and every driver spends less time waiting in the queue. So it seems obvious that more lanes always mean faster trips. But every extra lane also needs its own toll booth, its own signs, its own patrol car, and its own set of exits. Past a certain point, the cost of managing all those lanes starts to slow everyone down, and a highway with a hundred thin lanes can be slower than one with ten well-used lanes.

A Kafka topic is very much like this highway, and the partitions are the lanes. Engineers often hear two pieces of advice that seem to contradict each other: “add more partitions to go faster” and “too many partitions will hurt latency.” Both are true, and the skill lies in knowing which one applies to your system right now. This guide explains, from the very beginning and in plain language, exactly how the number of partitions affects every stage of a message’s journey, so that you can choose a partition count with confidence and explain your choice to others.

1The Big Question: Does More Mean Faster or Slower?

The honest answer is “it depends on which bottleneck you have,” and the rest of this guide shows how to tell.

Two different meanings of fast

People use the word fast to mean two different things, and mixing them causes most of the confusion. Throughput means how many messages the system can handle every second. Latency means how long a single message takes to travel from the moment it is created to the moment it is delivered and processed. A system can have excellent throughput and poor latency, like a freight train that carries enormous loads but takes a long time to arrive. It can also have low latency and modest throughput, like a courier on a motorbike.

Partitions are Kafka’s main tool for scaling throughput, because they allow many producers and many consumers to work in parallel. But partitions also add overhead to the brokers, the clients, and the cluster’s coordination machinery. Whether the net effect on latency is good or bad depends on whether the system is limited by too little parallelism or by too much overhead.

Simple Analogy

Think of a supermarket with checkout counters. If only two counters are open on a busy Saturday, customers wait in long queues, so opening more counters reduces waiting time. But if fifty counters are open and only a handful of customers arrive, the store wastes staff, customers wander between counters, and the manager spends the day coordinating instead of helping. The best number of counters matches the crowd.

The shape of the curve

If you measure latency while increasing the partition count on a fixed cluster, the result often looks like the letter U. At first, adding partitions reduces latency because work that was queuing behind a bottleneck now proceeds in parallel. Then the curve flattens, because parallelism is no longer the limiting factor. Finally, it starts to climb, because the overhead of managing so many partitions begins to cost more than the parallelism gains. The bottom of the U is the sweet spot, and where it lies depends on your hardware, your message rate, and your settings.

Too few
Work queues up behind a parallelism bottleneck
Just right
Parallelism is enough and overhead is small
Too many
Overhead and coordination dominate
i
A Promise About Numbers

This guide describes trends and mechanisms, not universal numbers. Real results depend on hardware, message size, replication settings, and client tuning, so the right partition count for your system must be found by measuring it. The guide shows you how.

2Latency From the Ground Up: The Journey of One Message

Before asking how partitions change latency, we must know where latency comes from in the first place.

The stages

A message passes through several stages between its creation and its use. Each stage adds a little waiting time, and end-to-end latency is the sum of all of them. Partition count touches almost every stage, which is why the topic is so rich.

1

Waiting in the producer

The producer does not send each message alone. It collects messages into batches per partition, and a message may wait for its batch to fill or for a short timer to expire.

2

Travelling to the leader and being written

The batch travels over the network to the broker that leads the partition, waits in a request queue, and is appended to the log.

3

Replication

Followers copy the batch from the leader. With the strongest acknowledgment setting, the producer waits for the in-sync followers before it is told the write succeeded.

4

Becoming visible

Consumers may read a message only after it is committed, meaning replicated to all in-sync replicas. The commit point is called the high watermark.

5

Fetching by the consumer

The consumer sends fetch requests. If no data is ready, the broker may hold the request for a short time, and then answers as soon as data arrives.

6

Waiting for processing

The message sits in the consumer’s memory until the application processes it, and if the consumer is busy, messages queue up behind others.

flowchart LR
    A["Message created"] --> B["Producer batch wait"]
    B --> C["Network to partition leader"]
    C --> D["Broker request queue and log append"]
    D --> E["Replication to in-sync followers"]
    E --> F["High watermark advances - message visible"]
    F --> G["Consumer fetch"]
    G --> H["Consumer processing queue"]
    H --> I["Message processed"]
        
FIG 1 — End-to-end latency is the sum of waiting at every stage of the message’s journey

Where partitions enter the story

Partition count influences the producer batch wait, because batches are formed per partition. It influences the broker’s write path, because every partition is a separate log. It influences replication, because followers must keep every partition in step. It influences consumer fetching and memory, because each partition is tracked separately. It influences the consumer processing queue, because partitions decide how many consumers can share the work. And it influences recovery time when something fails. The following chapters visit each of these in turn.

StageEffect of more partitionsDirection
Producer batchingSame traffic spread across more batches, so each fills more slowlyUsually worse
Broker write pathMore logs written at once, less sequential disk behaviorSlightly worse at scale
ReplicationMore partitions per follower fetch cycle, more bookkeepingWorse at scale
Consumer fetchMore partitions tracked per request, more memoryNeutral to slightly worse
Consumer processing queueMore consumers can share the loadBetter when processing is the bottleneck
Recovery from failureMore leaders to move and logs to recoverWorse
!
Common Misconception

Believing that partitions only affect throughput. They affect every stage above, and some of the effects are on latency directly, which is why a topic tuned for maximum throughput can be a poor choice for a latency-sensitive application.

3Partitions 101: What Is Actually Inside One

To understand the cost of a partition, it helps to see that each one is a real, physical thing with real resources attached.

A partition is a log on disk

A topic is divided into partitions, and each partition is an ordered, append-only sequence of messages. On the broker’s disk, a partition is a directory containing a series of segment files. Only the newest segment receives writes, and older segments are kept until they are deleted or compacted. Alongside each segment are index files that let the broker find a message by its position or by its timestamp without reading the whole segment.

Every partition also has a leader and, usually, two followers, so a topic with a hundred partitions and a replication factor of three has three hundred replicas spread across the brokers. Each replica is its own log directory, with its own open files and its own bookkeeping. The number of partitions therefore multiplies directly into the number of files, memory maps, and replication streams the cluster must manage.

Resource 1

Open file handles

Each segment and index of each replica keeps files open, so more partitions require a higher limit on open files.

Resource 2

Memory mapped indexes

Index files are mapped into memory, and operating systems limit how many maps a process may hold.

Resource 3

Replication streams

Every follower replica must keep pulling from its leader, so the number of streams grows with the partition count.

Resource 4

Metadata entries

The controller and every client hold information about each partition, its leader, and its replicas.

Resource 5

Producer state

Brokers remember recent sequence information per producer and partition to detect duplicates.

Resource 6

Active segments

Each partition has an active segment receiving writes, so many partitions mean many files written at once.

Simple Analogy

Every partition is like a separate notebook with its own bookmark, its own index tabs, and its own copies kept in other offices. A cabinet with ten notebooks is easy to manage. A cabinet with ten thousand notebooks needs shelves, labels, and a full-time librarian, even if most notebooks are barely used.

The partition as the unit of everything

A partition is the unit of ordering, because order is guaranteed only inside one partition. It is the unit of parallelism, because at most one consumer in a group reads a partition at a time. It is the unit of replication, because leaders and followers are assigned per partition. It is the unit of leadership, because one broker leads each partition. And it is the unit of failure recovery, because leaders are elected per partition. Since so many things attach to the partition, changing the number of partitions changes many things at once.

i
Counting Replicas, Not Only Partitions

When estimating load on a broker, count partition replicas, meaning leaders plus followers, not only partitions. A topic with sixty partitions and a replication factor of three adds one hundred eighty replicas to the cluster, and that is the number that decides the overhead each broker carries.

4The Good Side: Parallelism Removes Queues

Partitions reduce latency in one very important case: when messages are waiting in line because there are too few workers.

Queueing delay in plain language

Whenever work arrives faster than it can be handled, a queue forms, and every item in the queue waits. This waiting is called queueing delay, and it can dwarf every other source of latency. In Kafka, the consumers are often where queues form: if one consumer can process a thousand messages per second and a thousand and five hundred arrive, the extra five hundred pile up every second, and the delay of each new message grows without limit.

The number of partitions sets a ceiling on how many consumers in a group can work at the same time. A topic with four partitions can be shared by at most four active consumers of one group, however many you start. If the consumers are the bottleneck, and the partition count is the ceiling, then adding partitions and consumers removes the queue, and latency drops dramatically.

Simple Analogy

A restaurant kitchen with two cooks receives thirty orders every ten minutes but can cook only twenty. Orders pile up on the counter, and customers wait longer and longer. Hiring more cooks removes the pile, and the waiting time falls back to just the cooking time. Partitions are the number of cooking stations you make available for cooks to work at.

When the benefit is real

SymptomLikely bottleneckWill more partitions help?
Consumer lag grows, consumers show high processor useConsumer processing capacityYes, if consumers can be added up to the new partition count
Consumer lag grows, consumers are mostly idleSlow external calls or a small number of partitions limiting consumersPossibly; check whether there are fewer partitions than consumers
Producers wait for a single busy leaderOne overloaded partition or brokerYes, if traffic can be spread across partitions
Broker request queues are long, all brokers busyBroker capacityNo; more partitions add overhead, so add brokers instead
Latency spikes during failuresRecovery overheadNo; fewer partitions per broker usually helps

Throughput per partition sets the minimum

Each partition can sustain only a limited rate, set by the slower of the producer and the consumer side, and by the disk and network of the broker leading it. If a single partition can absorb, say, a certain number of megabytes per second, then to handle a target rate you need at least that many partitions, or the partitions become saturated and their queues grow. Being under this minimum causes both low throughput and high latency at once. Section on choosing a count later in this guide shows how to compute it.

i
First Rule of Partition Planning

Start with enough partitions that no single partition, no single consumer, and no single leader broker is saturated at your peak load. Everything else in this guide is about not overshooting that number by too much.

5The Producer Side: Batching Per Partition

The first place where too many partitions hurt latency is inside the producer, before the message even leaves the application.

How the producer batches

A Kafka producer collects messages into batches, and it keeps a separate batch for each partition it is writing to. A batch is sent when it reaches a size limit, set by the setting batch.size, or when it has waited for a time limit, set by linger.ms, whichever comes first. Batching is essential for efficiency, because sending one large batch is far cheaper than sending many tiny requests. It also improves compression, since compression works better on larger blocks of similar data.

Why more partitions make batches smaller

Suppose a producer sends a thousand messages per second. If the topic has ten partitions, each partition receives about a hundred messages per second. If the topic has a thousand partitions and messages are spread evenly, each partition receives one message per second. The batch for each partition fills a hundred times more slowly. So either the batch is sent almost empty, wasting effort, or the batch waits for the time limit, adding delay to every message inside it.

When the linger time is zero, the producer sends batches immediately, so latency for each message stays low, but the batches are tiny, and the number of requests grows. This increases load on the brokers and on the network, and can indirectly raise latency through queueing. When the linger time is greater than zero, batches become fuller, but every message may wait up to the linger time before being sent. Either way, spreading a fixed message rate over more partitions makes batching less effective.

flowchart TD
    A["Fixed producer rate"] --> B{"Partition count"}
    B -->|"Few partitions"| C["Each batch fills quickly"]
    B -->|"Many partitions"| D["Each batch fills slowly"]
    C --> E["Large efficient batches with small wait"]
    D --> F{"Linger time setting"}
    F -->|"Zero"| G["Tiny batches, many requests, more broker load"]
    F -->|"Positive"| H["Full batches but messages wait for the timer"]
        
FIG 2 — More partitions spread a fixed rate thinner, so batches fill more slowly
Simple Analogy

A delivery van leaves when it is full or when the clock says it must go. If a company has ten destinations, each van fills quickly. If it has a thousand destinations and the same number of parcels, each van waits with just a parcel or two, and it either leaves nearly empty or waits a long time. The road is not the problem; the number of separate vans is.

Keys make it stricter

When messages carry keys, the producer must send each key to the partition chosen by hashing it. The producer has no freedom to gather messages into fewer partitions. The batch for a partition contains only the messages whose keys map to it. With a large number of partitions and a moderate rate, batches for many partitions are nearly empty most of the time.

The sticky partitioner for messages without keys

For messages without keys, the producer has a choice of partition, and newer versions use it wisely. Instead of rotating through partitions one message at a time, the sticky partitioner keeps sending to one partition until its batch is full or has been sent, then switches to another. This concentrates messages into fewer batches and greatly reduces the penalty of a large partition count for keyless traffic. A later refinement adjusts the choice according to how quickly each broker is responding, so slower brokers receive fewer messages and are not allowed to hold up the stream.

Traffic stylePartition choiceEffect of high partition count on batching
Messages with keysFixed by the key hashStrong: batches per partition are thin
Messages without keys, old rotating choiceRound robin across all partitionsStrong: every batch is thin
Messages without keys, sticky choiceOne partition until the batch is fullSmall: batches stay full
i
Practical Tip

If your data has no natural key, do not invent one just to spread load. Let the producer use its sticky choice, which gives good spreading over time and keeps batches full. Use keys only when ordering or grouping requires them.

6Producer Memory and the Shape of Requests

Partition count also changes how much memory a producer needs and how its requests are shaped.

The buffer and the batch memory

A producer holds unsent messages in a memory buffer whose total size is set by buffer.memory. Each partition with pending messages takes a batch’s worth of memory, up to the batch size. If a producer writes to thousands of partitions at once, the memory needed for open batches can approach or exceed the buffer. When the buffer is full, the send call blocks, waiting for space, and that waiting is pure latency added to the application.

This is a common surprise in systems that grow their partition count without resizing producer memory. Nothing else changes, the message rate stays the same, and yet the producer begins to block during bursts. The cure is either a bigger buffer, a smaller batch size, or fewer partitions.

Requests are grouped by broker

The producer does not send one request per partition. It groups all ready batches destined for the same broker into a single request. This softens the cost of many partitions, because a request to one broker can carry batches for many of its partitions. But the request still contains a separate section for each partition, the broker must process each section, and the response must acknowledge each one. So the per-partition overhead does not vanish, it is only shared inside a request.

1

Messages arrive at the producer

Each message is placed in the open batch of its partition, taking memory from the buffer.

2

Batches become ready

A batch is ready when it is full or its wait time has expired.

3

Ready batches are grouped by broker

All ready batches for partitions led by the same broker travel in one request.

4

The broker processes each partition section

It appends each batch to the correct log, and the response reports the result for every partition.

In-flight limits and ordering

A producer limits how many requests it may have unanswered for each broker connection. This limit protects ordering and idempotence, but it also means that if a broker is slow, requests wait in line behind each other. With many partitions per broker and small batches, the number of requests can climb, and the in-flight limit can become the bottleneck that adds latency.

Producer resourceHow partition count affects itSymptom when strained
Buffer memoryMore open batches take more memorySend calls block waiting for space
Batch efficiencyThinner batches per partitionHigher request rate, lower compression gains
Request sizeMore partition sections per requestSlower request processing at the broker
In-flight slotsMore small requests compete for few slotsQueueing in the producer, added delay
MetadataClient tracks more partitionsLarger metadata refreshes and more memory
!
Do Not Forget the Clients

Partition count is often changed by the platform team while producer settings belong to application teams. After raising a partition count, review producer buffer, batch, and linger settings, since they were tuned for the old shape of traffic.

7The Broker Write Path: Many Active Logs

Once a batch reaches the broker, the number of partitions that broker hosts changes how smoothly the disk, the memory, and the operating system can serve it.

Appending is cheap, and that is the secret

Kafka is fast because writing to a log is an append at the end of a file. The operating system takes the bytes, stores them in a memory area called the page cache, and flushes them to disk later in large, friendly chunks. A broker does not force every message to disk before answering, because safety comes from replication rather than from flushing each write.

Simple Analogy

Imagine a clerk who writes new entries at the bottom of one long notebook. Turning pages is never needed, so the clerk is very quick. Now give the same clerk five hundred notebooks and ask them to write a line in each one every minute. The clerk keeps jumping between notebooks, opening and closing covers, and losing their place. The writing itself is still simple, but the jumping adds up.

Sequential turns into scattered

With a handful of active partitions per disk, the writes form a few steady streams, and the operating system can group them well. With thousands of active partitions on the same disk, the flushes go to many different files at once. On spinning disks this scattering is painful because the head must move. On modern flash storage it is much less painful, but it still reduces the efficiency of grouping and can make the moment of a flush more bursty.

i
Disk Type Matters

The same partition count can be comfortable on fast flash storage and uncomfortable on slow disks. When you compare guidance from different sources, check what hardware they used, because the scattering cost depends on it strongly.

The page cache is shared

The page cache is one pool of memory shared by every partition on the machine. Each active partition wants its recent data to stay in that pool so that consumers reading fresh messages are served from memory rather than from disk. When there are many partitions, each one gets a thinner slice of the pool. If consumers keep up, they read very recent data and the pool works well. If some consumers fall behind, they read older data that may have left the cache, and those disk reads compete with the writes, which raises latency for everyone on that broker.

File handles and memory maps

Every partition replica is a directory of segment files, and each segment has index files. The broker keeps many of these open and maps the index files into memory. That leads to two operating system limits that matter when the partition count grows.

Limit 1

Open file descriptors

Each open segment and index consumes a descriptor. If the limit is too low, the broker fails to open or create files, and requests fail with errors rather than merely slowing down.

Limit 2

Memory map count

Each mapped index counts against a per-process limit on the operating system. Reaching it can stop a broker from creating new segments, and the failure appears suddenly instead of gradually.

!
Cliffs Are Worse Than Slopes

Most partition costs add a small amount of latency for each new partition, a gentle slope. Operating system limits are different. You feel nothing until you hit the limit, and then things break. Raise these limits before growing partition counts, and watch usage as a percentage of the limit.

Segment rolling and retention across many logs

Every log rolls a new segment when the current one is full or old enough, and background threads delete old segments according to retention. With many partitions, these small events happen very often somewhere on the broker. Each roll creates files and indexes, and each deletion removes them. Individually these are quick, but with thousands of logs, the constant background activity uses the same disk and threads that serve client requests.

Log flushing and the recovery cost

After an unclean shutdown, the broker must check the logs that were being written when it stopped. More partitions means more logs to check, so the broker takes longer to become useful again. This is not steady-state latency, but it belongs to the latency story, because a slow restart extends the period during which clients see delays. Chapter 11 returns to this.

Broker resourceEffect of many partitionsWhat to watch
Disk writesMore scattered flushes, burstier behaviorDisk utilization, write wait times
Page cacheThinner share for each partitionDisk read rate for consumers that should read from memory
File descriptorsOne set per segment and indexOpen descriptors compared with the limit
Memory mapsOne per index fileMap count compared with the limit
Background threadsMore rolls, deletions, and cleaningLog flush time, thread idle percentage

8Replication Latency: The Hidden Multiplier

Replication is where partition count often has its largest effect on latency, because every partition must be copied, and copying has a fixed cost per partition.

How followers copy data

A follower replica works like a consumer. It sends fetch requests to the leader of each partition it follows and appends what it receives. A follower broker does not open one connection per partition. Instead, a small number of fetcher threads each handle a group of partitions that share the same leader broker, bundling them into one request.

Simple Analogy

A delivery driver collects parcels for many houses in one street. One driver with a full van is efficient. But if the street grows to a thousand houses and there is still one driver, each house waits longer for a turn, even if each parcel is tiny. Adding drivers helps, but each driver needs a van, and the depot gets busier.

Why partitions add delay here

A fetcher thread must cycle through its assigned partitions on every round. Each round involves preparing the request, waiting for the leader to answer, and applying the data to each partition log. If a fetcher is responsible for a very large number of partitions, one round takes longer, so new data on any single partition may wait for the round to come back to it. That waiting is added to the time before a message is considered committed.

An often-quoted early measurement, from the period when Kafka guidance about partition counts was first written down, showed that replicating around a thousand partitions from one broker to another with a single fetcher added noticeable delay, on the order of tens of milliseconds. Treat that figure as an illustration of the mechanism rather than a promise, because hardware, software versions, and settings have changed a great deal since then.

Fetch sessions reduce the burden

Newer Kafka versions use incremental fetch sessions. Instead of listing every partition in every request, the follower and the leader remember the list, and each request mentions only the partitions that have changed. This greatly reduces the cost of many quiet partitions, because a partition with no new data no longer adds to the request size. Partitions that are actively receiving data still cost work, so the gain is largest when many partitions are idle.

Waiting at the leader: the purgatory

With the strongest acknowledgment setting, the leader cannot answer the producer until enough followers have caught up. The waiting produce request is parked in a structure called the purgatory. Followers also send fetch requests that the leader may hold for a short time when there is no new data. Each partition with active traffic contributes waiting requests and wake-up events. More partitions with active traffic means more of this bookkeeping, and it happens on request-handling threads shared by all partitions.

1

Leader appends the batch

The batch lands in the leader log, and the produce request is parked until followers confirm.

2

Follower fetcher comes around

The fetcher thread that covers this partition sends its next request. The wait for its turn grows with the number of partitions it covers.

3

Follower writes and reports progress

The follower appends the data and, in its next fetch, tells the leader how far it has read.

4

High watermark moves and the producer is answered

Once all in-sync followers have caught up, the message is committed, the parked request completes, and consumers may read it.

sequenceDiagram
    participant P as "Producer"
    participant L as "Leader broker"
    participant F as "Follower broker"
    P->>L: "Produce batch for partition"
    L->>L: "Append to log and park request"
    F->>L: "Fetch round covering many partitions"
    L-->>F: "New data for the partition"
    F->>F: "Append to follower log"
    F->>L: "Next fetch reports progress"
    L->>L: "Advance high watermark"
    L-->>P: "Acknowledge the batch"
        
FIG 3 — The follower fetch round is the step whose duration grows when a fetcher covers many partitions

Read the diagram from top to bottom. The producer sends a batch and waits. The leader stores it and parks the request. The follower’s next fetch round retrieves the data. Then the follower’s following fetch carries the progress report that lets the leader move the high watermark and answer. The two fetch rounds in the middle are the part that stretches when a follower is busy with too many partitions.

Acknowledgment settings change who feels this

acks = 0

Fire and forget

The producer does not wait, so replication latency does not reach it. Consumers still see the message later, because visibility depends on replication.

acks = 1

Leader only

The producer waits only for the leader append, so its send latency ignores replication. Consumers still wait for the high watermark.

acks = all

All in-sync replicas

The producer waits for replication, so it feels the full cost of follower fetch rounds. This is the safe setting and the one most affected by partition count.

Levers on the follower side

Two settings matter most. The first is the number of replica fetcher threads on each broker. Raising it spreads partitions over more threads, so each thread covers fewer partitions and each round is shorter. The second is how long a leader holds a follower’s fetch request when no data is available. Shorter holds react faster but create more requests. Each extra thread costs some CPU and connections, so raise the count gradually and observe.

i
Skew Makes It Worse

If one broker leads many busy partitions while another leads few, the followers of the busy broker carry most of the load. Balanced leadership across brokers keeps each fetcher’s round short, so balance is as important as raw count.

9The Consumer Side: Fetching, Assignment, and Memory

Consumers are affected in a mixed way: more partitions allow more consumers to share the work, but each consumer that reads many partitions pays extra costs.

How a consumer fetches

A consumer sends fetch requests to the brokers that lead the partitions it owns. Each request may include several partitions from the same broker. The broker answers when either a minimum amount of data is available or a maximum waiting time has passed. Two settings control this balance: a minimum byte threshold and a maximum wait time. A large minimum with a long wait means efficient but slow-arriving data, and a tiny minimum means fast but chatty fetching.

Simple Analogy

Picture a student who collects homework from several friends. She can walk to each friend after every single page is written, which is quick to receive but tiring, or she can wait until each friend has a stack, which is efficient but slow. If she has to visit fifty friends instead of five, one full round takes ten times longer, whichever style she uses.

Many partitions per consumer

When the number of consumers is smaller than the number of partitions, each consumer owns several partitions. It must visit all of them, and the data it receives per round is spread across many logs. The client has a limit for how much data it accepts per partition in one response, and another limit for the whole response. Because the memory that a consumer may need grows with the number of partitions it owns times the per-partition limit, the settings must be sized with partition count in mind.

SituationConsumer effectLatency impact
Few partitions, slow processingOnly a few consumers can work in parallelBacklog grows, processing delay rises
Balanced partitions and consumersEach consumer owns a manageable setLow and steady delay
Very many partitions per consumerLarge memory need, long fetch roundsFetch and processing become uneven
More consumers than partitionsExtra consumers sit idleNo gain, wasted resources

The ceiling of consumer parallelism

Within one consumer group, a partition is read by at most one consumer at a time. This means the partition count is the maximum useful number of consumers. If your processing is slow and you need forty consumers, you need at least forty partitions, or the extra consumers will do nothing. This is the strongest argument for having more partitions, and it is a latency argument, since it removes queueing in the processing stage.

Fairness between partitions

A consumer reading many partitions gets data from them in rounds. If one partition is very busy and others are quiet, a poorly tuned consumer may spend its capacity on the busy one. Modern clients try to rotate fairly, but you may still observe uneven delays across partitions. Uneven delays are a warning that some partitions receive far more traffic than others, which chapter 14 discusses.

Processing time dominates surprisingly often

In many real systems, the time to process a message is larger than all the time spent in Kafka. In that case, the useful question is not “how do partitions change Kafka’s latency” but “how many parallel workers does my processing need.” Adding partitions to enable more workers can cut end-to-end latency by far more than any tuning inside Kafka, and the overhead of the extra partitions is small compared with that gain.

i
Measure the Whole Path First

Before changing partition counts, measure how much of your end-to-end delay is queueing in the consumer. If most of it is consumer lag caused by slow processing, more partitions and more consumers are the answer. If most is in the broker or replication, more partitions may make things worse.

Consumer memory and heap pressure

Each fetched batch is held in memory until the application processes it. A consumer with a large number of partitions and generous per-partition limits may hold a lot of data at once. Garbage collection pauses in the consumer show up as end-to-end latency, even though Kafka itself is healthy. Watch the consumer’s memory and pause times when raising partition counts.

10Rebalances and Startup Latency

Some latency is not about a single message at all. It is about the pauses that happen when the group of consumers changes.

What a rebalance is

When a consumer joins, leaves, or stops responding, the group must decide who reads which partitions. During that decision, some or all consumers may pause. The pause is a period in which no messages are processed for the affected partitions, so any message that arrives waits. For a system that promises low latency, a rebalance is a real event, and its length depends on how much the group has to decide.

Simple Analogy

A teacher divides a reading list among students. If a student joins mid-lesson, the teacher pauses the class and hands out the list again. With ten books, this takes a minute. With ten thousand books, the teacher spends a long time writing names, and each student must copy down their new list before starting again.

How partition count lengthens the pause

1

Metadata gathering

Members and the coordinator must know the full list of partitions for every subscribed topic. Larger lists mean larger messages and more processing.

2

Assignment computation

The assignor calculates who gets each partition. The work grows with partitions and members, and sticky assignors do extra work to keep assignments stable.

3

Distributing the assignment

The result is sent to every member, so bigger assignments mean bigger messages.

4

Fetching committed offsets

Each member asks for the last committed position for each of its partitions before it can start reading. More partitions means more offsets to look up.

5

Resuming and warming up

Members create fetch state for each partition, and for stateful applications, restore local state before processing.

flowchart TD
    A["Membership change"] --> B["Group pauses affected partitions"]
    B --> C["Assignment computed for all partitions"]
    C --> D["Assignment sent to every member"]
    D --> E["Members fetch committed offsets"]
    E --> F["State restored if the application is stateful"]
    F --> G["Processing resumes and backlog drains"]
    G --> H["Latency returns to normal"]
        
FIG 4 — Each step of a rebalance grows with partition count, and the backlog built during the pause must be drained afterwards

The last two steps deserve attention. While the group was paused, messages kept arriving. When processing resumes, those messages form a backlog, and even after the pause ends, the latency for new messages stays high until the backlog is drained. So the visible effect of a rebalance is longer than the pause itself.

Stateful applications feel it most

Stream processing applications keep local state for each partition they process, and that state is rebuilt from a changelog if it moves to another instance. More partitions means more state stores to move and restore. Restoring can take minutes for large state, which is a huge latency event compared with a normal message delay. Standby replicas and careful assignment can reduce the pain, but they cost resources.

Reducing rebalance cost

Idea 1

Cooperative assignment

Incremental rebalancing moves only the partitions that must move, letting the rest continue to work, so the pause is limited to a few partitions.

Idea 2

Static membership

Giving members stable identities lets a quick restart return to the same assignment without triggering a full rebalance.

Idea 3

Sensible timeouts

Session and poll timeouts that match real processing times prevent needless evictions that cause extra rebalances.

!
Deployments Trigger Rebalances

A rolling deployment of consumers causes a series of membership changes. With a large partition count, each change is expensive. Plan deployments knowing that partition count multiplies the cost of every restart.

Newer group protocols move more of the work to the broker side and aim to make rebalances lighter, so the details depend on the Kafka version you run. Check your version’s documentation to see which protocol and assignors are available to you.

11Failure Latency: Leader Elections and Recovery

Systems are judged not only on a calm day but on the day something breaks, and partition count strongly shapes how long that day feels.

What happens when a broker dies

Every partition needs a leader. When a broker fails, every partition it led loses its leader, and each of those partitions must elect a new one from its in-sync followers. Until a new leader is chosen and clients learn about it, producers and consumers of that partition get errors or timeouts and must retry.

Simple Analogy

A school has many classes, each with a class captain. If a teacher who supervised two hundred classes suddenly goes home sick, all two hundred classes need a new captain named at once. If the school has only twenty classes per teacher, the change is done in a moment. The more classes a single teacher supervised, the longer the school is confused.

The unavailability window

The time during which a partition has no working leader is a hole in availability. Its length is roughly the time to detect the failure, plus the time to elect leaders for all affected partitions, plus the time for the new information to reach clients. The middle part scales with the number of partitions that were led by the failed broker. With a single controlled shutdown, leadership is moved gracefully before the broker stops, so the hole is small. With a crash, it is not graceful, and the cost is visible.

1

Detection

The cluster notices that the broker stopped sending heartbeats or lost its session. The detection timeout is a fixed cost that does not depend on partition count.

2

Election

The controller picks a new leader for every partition that was led by the failed broker. Work grows with the number of such partitions.

3

Propagation

The controller tells the affected brokers, and the updated metadata reaches all brokers so that they can answer client questions correctly.

4

Client refresh

Clients discover the new leaders through errors and metadata refreshes and then resume sending and fetching.

flowchart LR
    A["Broker fails"] --> B["Failure detected after timeout"]
    B --> C["Controller elects new leaders for each affected partition"]
    C --> D["New leadership propagated to brokers"]
    D --> E["Clients refresh metadata"]
    E --> F["Traffic resumes on new leaders"]
        
FIG 5 — Only the election and propagation stages grow with the number of partitions on the failed broker

Follow the arrows from left to right. Detection takes about the same time no matter what. Election and propagation are the stages that stretch when the failed broker led thousands of partitions. Client refresh depends on client settings, but larger metadata takes longer to fetch and process.

The controller as a bottleneck

In older architectures based on ZooKeeper, the controller broker handled failover by reading and writing per-partition information in the coordination service, so its work was strongly proportional to the number of partitions and the recovery could be slow for very large clusters. Newer architectures based on the built-in Raft quorum, often called KRaft, keep metadata in a replicated log and make controller failover and metadata propagation more efficient, which is why they support much larger partition counts. The exact improvement depends on your version and setup, so read the release notes for the version you run before relying on it.

Recovery after restart

When a broker comes back, it must reload its logs, rebuild any indexes that were not cleanly closed, and catch up with the leaders. More partitions means more logs to open, so the restart takes longer. During this time the broker holds fewer leaders or none, and the cluster runs with less redundancy. Configuring several threads for log recovery per data directory can shorten this phase.

Failure phaseDepends on partition count?Ways to shorten
DetectionNoTune session and heartbeat timeouts carefully
ElectionYes, stronglyFewer partitions per broker, modern controller design
PropagationYesModern metadata design, smaller clusters per controller
Client refreshSomewhatSensible retry and metadata refresh settings
Restart recoveryYesMore recovery threads, clean shutdowns
i
Use Controlled Shutdown

Stopping a broker gracefully lets it hand over leadership before it leaves, one partition at a time, so clients barely notice. Always prefer this for maintenance, and treat crash recovery time as the design limit for your partition count.

12Control Plane Load: Metadata Everywhere

Besides moving messages, a Kafka cluster must keep track of itself, and that bookkeeping grows with the number of partitions.

The two planes

Engineers often speak of a data plane and a control plane. The data plane carries messages between clients and brokers. The control plane manages the facts about the cluster: which topics exist, which broker leads each partition, which replicas are in sync, and what configuration applies. Partition count barely changes the size of a single message, but it grows the control plane linearly, because every partition is one more fact to store, update, and share.

Simple Analogy

Think of a school office keeping a register of where every student sits. With thirty students, the register fits on one page and updates are instant. With thirty thousand students, the register is a thick book, every seat change means updating the book, and every teacher who wants a fresh copy must wait for photocopies.

Where the metadata goes

Place 1

The controller

Holds the complete picture and makes every leadership and replica-state decision. Its load grows with partitions and with the rate of changes.

Place 2

Every broker

Keeps a cache of metadata so it can answer clients. Each update must be applied by every broker, so the cost multiplies by cluster size.

Place 3

Every client

Producers and consumers fetch metadata for the topics they use. Applications that touch many topics or partitions hold larger caches and process larger responses.

Metadata churn and request latency

Whenever something changes, such as a leader moving or a replica dropping out of sync, updates are sent out. In a cluster with a very large number of partitions, changes happen more often simply because there are more things that can change, and each update carries more data. Brokers spend more time applying updates, and that work competes with serving requests. The visible effect is an occasional rise in request latency around events like rolling restarts or partition reassignment.

1

A state change occurs

A replica falls behind, a broker restarts, or an operator moves a partition.

2

The controller records it

The change is written to the durable metadata store and turned into updates for brokers.

3

Brokers apply the update

Each broker updates its cache and adjusts its own fetchers and logs where needed.

4

Clients learn about it

Clients see the change through errors or scheduled refreshes and update their own view.

Client-side effects

A producer that writes to a topic with many partitions must know the leader of each one, and it refreshes this information periodically and after errors. A larger topic means larger refreshes. Consumers that subscribe by pattern, matching many topics, can be especially expensive, because every metadata refresh must be checked against the pattern, and any change in matching topics may trigger a rebalance. Applications with thousands of short-lived clients, such as serverless functions, multiply the effect, because each new client asks for the full metadata.

!
Many Small Topics Versus Few Large Ones

Total partition count across the cluster is what loads the control plane, not the count in any single topic. A design that creates a separate topic for every customer, each with several partitions, can reach a huge total quickly. Consider whether keys within a shared topic can serve the same purpose.

Operations that stress the control plane

Rolling restarts, mass topic creation, large reassignments, and broker replacements all cause bursts of metadata change. If they are done gently, one step at a time, a cluster with many partitions handles them well. If they are done all at once, latency spikes appear. Throttle reassignment traffic and spread operations over time.

Control plane componentGrows withLatency symptom
ControllerTotal partitions and change rateSlow failover and slow topic operations
Broker metadata cacheTotal partitionsRequest time spikes during updates
Client metadataPartitions in the topics usedSlow startup, large refresh responses
Group coordinationPartitions consumed by a groupLong rebalances

13Tail Latency: Why the Slowest Messages Matter Most

Averages hide pain. The messages that suffer most are the ones that reveal what partition count really does to your system.

Average, median, and tail

If you line up a thousand message delays from shortest to longest, the median is the one in the middle, and the ninety-ninth percentile is the delay that only one message in a hundred exceeds. The far end is called the tail. An average can look wonderful while the tail is terrible, because a few very slow messages barely move the average. Users and downstream systems, however, often experience the tail, since one slow message can hold up an entire order or workflow.

Simple Analogy

Imagine a school bus that is on time for ninety-nine days and stuck in a traffic jam on the hundredth. The average arrival time looks great, but on the hundredth day a child misses the first lesson. The child remembers that day, not the average.

How many partitions stretch the tail

A single message rarely waits on only one partition. A request that carries batches for many partitions is only complete when the slowest partition section is done. The more partitions involved, the higher the chance that at least one of them is having a bad moment, so the request as a whole is slower than the typical partition. This is a general effect of fan-out: the more independent pieces a task waits for, the more its delay follows the slowest piece.

Fan-out
More partitions per request means more chances of one slow piece
Sharing
Shared threads and disks make slow moments spread between partitions
Rare events
Garbage collection, flushes, and leader moves hit the tail first

Common tail sources related to partitions

Source 1

Batch waiting

Quiet partitions keep their batches open until the timer expires, so the message in a quiet partition always pays the full linger time.

Source 2

Follower rounds

A partition whose follower is busy with many others waits longer for its turn in a fetch round.

Source 3

Disk bursts

Flush activity across many logs can produce short stalls that delay whichever requests are being handled at that moment.

Source 4

Hot partitions

One partition that receives disproportionate traffic queues messages behind each other, even if others are idle.

flowchart TD
    A["Producer request with many partition sections"] --> B["Section for partition 1 - fast"]
    A --> C["Section for partition 2 - fast"]
    A --> D["Section for partition 3 - delayed by disk burst"]
    A --> E["Section for partition 4 - fast"]
    B --> F["Request response waits for all sections"]
    C --> F
    D --> F
    E --> F
    F --> G["Slowest section decides the request latency"]
        
FIG 6 — A request that touches many partitions is as slow as its slowest partition section

In the picture, three of the four partition sections finish quickly. The third is delayed by a short disk burst. Because the response is sent as one piece, all four batches in that request are acknowledged only when the third is done. This is how a small problem in one partition is felt by many messages.

Watching the right numbers

Always look at percentiles, not only averages. Record the median, the ninety-fifth, the ninety-ninth, and the maximum for each stage. Compare them before and after changing partition counts. If the median stays the same but the ninety-ninth percentile climbs, you have found the cost of too many partitions or of too much sharing.

i
Beware of Coordinated Omission

Test tools that wait for each reply before sending the next message can hide long delays, because they stop sending during the stall and therefore never record the messages that would have suffered. Use tools that send at a fixed rate regardless of replies, so slow moments show up in the numbers.

14Ordering, Keys, and Growing Partition Counts

Choosing a partition count is not only a performance decision. It is tied to how messages with the same key are kept together and in order.

Keys decide the partition

When a message has a key, the default partitioner runs the key through a hash function and picks the partition using the result and the partition count. All messages with the same key go to the same partition, which is how Kafka keeps them in order. This is a valuable promise, because consumers can process all events for one customer or one order in sequence.

Simple Analogy

A library sorts books into shelves by the first letter of the title. Everyone knows that a given title always sits on the same shelf. If the library suddenly changes to twice as many shelves and sorts by a new rule, many books now belong on different shelves. Anyone who remembers the old shelf will look in the wrong place.

Adding partitions changes the mapping

Because the partition depends on the count, increasing the number of partitions changes where many keys go. After the change, a key that used to land on partition three may land on partition eight. New messages for that key go to a different partition than the older ones, so per-key ordering across the change is no longer guaranteed. A consumer that keeps state per key may find that the key’s history is on one instance while its new messages arrive at another.

1

Before the change

Key A always goes to partition 3, so all its messages are in order in one place.

2

Partition count grows

The hash result is now divided differently, so key A maps to partition 8.

3

Old and new messages split

Older messages for key A remain on partition 3, while new ones go to partition 8, and two consumers may process them at the same time.

4

Ordering promise weakens

A newer message may be handled before an older one for the same key, until the older ones are drained.

flowchart LR
    K["Message key A"] --> H["Hash of the key"]
    H --> M1["Divide by 4 partitions - result is partition 3"]
    H --> M2["Divide by 8 partitions - result is partition 8"]
    M1 --> P3["Partition 3 holds old messages"]
    M2 --> P8["Partition 8 receives new messages"]
        
FIG 7 — The same key can map to a different partition after the partition count is changed

The diagram shows one hash result used with two different counts. Before growth, it selects partition three. After growth, it selects a different partition. The old data stays where it was written, because Kafka never moves existing messages between partitions.

Why this matters for latency planning

Since raising the count later is disruptive for keyed data, teams often choose a large count at the start to leave room for growth. That is the reason many topics begin with more partitions than they need today. The trade-off is that the overheads from the previous chapters begin immediately. A sensible approach is to plan the count for your expected growth over a reasonable period, and to design keyed consumers so that they tolerate a one-time reshuffle if it ever becomes necessary.

!
Partitions Cannot Be Reduced

Kafka lets you add partitions to a topic but not remove them. If you overshoot, the only way back is to create a new topic with fewer partitions and migrate the data and clients. Because the decision is one-way, it is wise to be careful when increasing.

Hot partitions and skew

More partitions only helps if traffic spreads evenly. If a few keys account for most of the messages, their partitions become hot while the others sit idle. Extra partitions do not help, since a hot key still lands in one partition. The symptoms are one partition with high consumer lag while others are fine, and one broker with much higher load. Options include splitting a hot key into several sub-keys, using a different key, or accepting that hot keys need special handling.

Key patternDistributionEffect on latency
Many keys, similar trafficEvenParallelism works as expected
Few keys, similar trafficOnly as many partitions used as keysExtra partitions idle, no gain
A few very busy keysSkewedHot partitions queue up, tail latency grows
No keysBatch-sticky spreadEven load, but no per-key ordering

Custom partitioners

If the default hash does not spread your traffic well, a custom partitioner can route by your own logic, for example sending large tenants to dedicated partitions. This gives control but also creates responsibility, because the routing rules must stay consistent between all producers and be handled carefully when the partition count changes.

15Transactions and Compaction: Two Features That Multiply Partition Cost

Some Kafka features do extra work for every partition they touch, so a high partition count makes them relatively more expensive.

Transactions touch every participating partition

A transactional producer can write to several partitions and then commit or abort them all together. To do this, the transaction coordinator must remember every partition in the transaction, and when the transaction ends, it writes a small marker into each of those partitions. Consumers that read only committed data wait for that marker before they can pass the transaction’s messages.

Simple Analogy

Suppose a teacher hands out exam papers across many rooms, and the exam is valid only when every room signs the “finished” sheet. The more rooms there are, the more signatures are required, and the exam result is delayed until the slowest room signs.

1

Register partitions

Each new partition written to in the transaction is reported to the coordinator.

2

Decide the outcome

When the producer commits, the coordinator records the decision durably.

3

Write markers

The coordinator sends a marker to every partition in the transaction, and each leader appends it and replicates it.

4

Readers move past the transaction

Consumers using the committed-read mode can deliver the transaction’s messages once the marker is visible in their partition.

The consequence is that the delay to see committed transactional data has a part that grows with the number of partitions involved in the transaction, plus the time for the slowest leader to write its marker. Short transactions that touch few partitions are cheap. Long transactions that touch hundreds of partitions have visible latency. Interval settings for commits also matter, since a transaction that stays open for a long time holds back consumers reading committed data on all the partitions it touched.

i
Design Tip

Keep each transaction focused on as few partitions as your logic allows, and keep commit intervals short when downstream latency matters. Batching a huge number of partitions into one transaction saves coordinator calls but delays visibility.

Compaction across many logs

Compacted topics keep only the latest value for each key. A pool of cleaner threads scans logs that have enough obsolete data, rewrites them without the old entries, and swaps them in. When there are many compacted partitions, the cleaner must spread its attention across all of them. Each cleaning pass reads and writes a lot of data, so it competes with client traffic for the disk. Consumers of compacted topics may also see delay if the cleaner falls behind, since old segments grow and restarts take longer to rebuild state.

Effect 1

Disk contention

Cleaning reads and rewrites data, taking disk bandwidth away from producers and consumers, and the effect grows with the number of logs to clean.

Effect 2

Cleaner backlog

If there are more dirty logs than the cleaner can handle, logs stay large, which lengthens restarts and state rebuilds.

Effect 3

Small segments

Many low-traffic partitions may hold tiny segments that take long to fill and clean, wasting file handles.

Internal topics also have partitions

Kafka keeps internal topics for consumer group offsets and for transaction state. These have their own fixed partition counts, and the coordinators for groups and transactions are the leaders of those partitions. The number of internal partitions determines how many brokers can share coordinator work. Changing them after the cluster is in use is difficult, so it is decided early, and it is worth checking that the values suit a cluster of your size.

16The U-Shaped Curve: Putting It All Together

Now that each cost and benefit has been examined, we can join them into one story that explains why latency first falls and then rises.

Forces pulling in opposite directions

Some forces reduce latency as partitions increase: more parallel consumers, shorter queues, and lower load per partition. Other forces increase it: thinner producer batches, more replication bookkeeping, heavier metadata, longer rebalances, and slower recovery. Total latency is the sum of both. At small counts the first group dominates, so latency falls. At large counts the second group dominates, so latency rises. The minimum is where the two balance.

Simple Analogy

Think of a group project. Adding a second and third student greatly speeds up the work. Adding a tenth student helps a little. Adding the fiftieth student slows everything down, because most of the time goes into meetings, splitting tasks, and sharing updates. The best team size is somewhere in the middle.

flowchart LR
    A["Very few partitions"] --> B["Queues form behind a parallelism limit"]
    B --> C["Increasing partitions removes queues"]
    C --> D["Sweet spot: enough parallelism, small overhead"]
    D --> E["Increasing further adds overhead faster than it removes queues"]
    E --> F["Many partitions: latency rises again"]
        
FIG 8 — Latency falls while parallelism is the bottleneck and rises when overhead becomes the bottleneck

The diagram is a story in six steps. On the left, too few partitions create queues. Moving right, added partitions remove those queues. In the middle is the sweet spot. Further right, each extra partition adds more overhead than it removes queueing, and latency climbs.

Three regimes

RegimeDominant problemWhat adding partitions doesTypical signs
Too fewQueueing for parallel capacityHelps a lotConsumer lag, busy single threads, long queue times
BalancedMixed small costsLittle effect either wayStable latency, healthy utilization
Too manyOverhead per partitionHurtsThin batches, long rebalances, slow failover, metadata spikes

Why the sweet spot moves

Mover 1

Message rate

Higher traffic fills batches faster, so more partitions can be afforded before batches become thin.

Mover 2

Hardware

Faster disks, more memory, and more CPU cores push the point where overhead bites to a higher count.

Mover 3

Cluster size

More brokers share the partitions, so each broker carries fewer for the same total.

Mover 4

Software version

Improvements in fetch sessions and metadata handling raise the practical limits over time.

Partition count is a dial, not a switch. Turn it slowly and watch the gauges.

The curve is not symmetrical

The left side of the U is usually steep, because a real bottleneck can cause enormous queueing. The right side is usually gentle at first and then sudden, because overhead builds slowly and then hits limits. That asymmetry teaches a useful lesson: being somewhat above the sweet spot is usually cheaper than being below it, as long as you stay away from the cliffs at the far right.

17How to Choose a Partition Count

A practical method starts with the throughput you need and then checks it against the latency costs.

Start with throughput

Measure, or estimate, how fast one partition can accept data on the producer side and how fast one consumer can process data on the consumer side. Then compute how many partitions you need to reach your target rate for each side. Take the larger of the two. If a single partition handles a modest rate for production and a lower rate for consumption because processing is slow, the consumer side decides the count.

Simple Analogy

If you must move a thousand boxes an hour and each worker carries fifty boxes an hour, you need twenty workers. If each also needs a helper who handles only thirty boxes an hour, you need about thirty-four helpers, and the slower group sets the team size.

1

Define the target

Decide the peak data rate, and include growth for the period you plan for, not only today’s rate.

2

Measure per-partition capacity

Test how much a single partition can absorb on the producer side and how much one consumer can process.

3

Divide and take the larger result

Target rate divided by per-partition capacity for each side gives two numbers, and the larger one is the minimum.

4

Add headroom

Leave room for bursts, key skew, and growth, often somewhere between one and a half and three times the minimum, depending on how costly future changes are.

5

Check the per-broker load

Multiply by the replication factor and divide by the number of brokers, and compare with the level your hardware and version comfortably handle.

6

Test latency at that count

Run load tests at the proposed count and one step above and below, and compare the percentiles.

flowchart TD
    A["Target peak throughput"] --> B["Divide by producer capacity per partition"]
    A --> C["Divide by consumer capacity per partition"]
    B --> D["Take the larger result"]
    C --> D
    D --> E["Add headroom for bursts and growth"]
    E --> F["Check partitions per broker including replicas"]
    F --> G{"Within comfortable limits?"}
    G -->|"Yes"| H["Load test and compare latency percentiles"]
    G -->|"No"| I["Add brokers or reduce the count"]
    I --> F
        
FIG 9 — A count is chosen from throughput, adjusted for headroom, and then checked against broker limits and measured latency

The decision node near the end is the guard against overshooting. If the per-broker count is too high, you have two honest options: add brokers so each carries fewer partitions, or reduce the plan. Then the loop repeats until the check passes.

Rules of thumb, carefully used

You may see guidance such as “a few thousand partition replicas per broker” or “a hundred thousand across a cluster” for classic setups, and higher numbers for newer metadata designs. Such numbers are useful as an order of magnitude and as a warning that the range is not unlimited. They are not guarantees, and they change with versions. Use them to know when to be careful, then verify with your own tests.

!
Count Replicas, Not Only Partitions

A topic with one hundred partitions and a replication factor of three is three hundred partition replicas spread across brokers. Broker limits apply to replicas, including follower replicas, so always multiply by the replication factor when checking capacity.

Different topics, different counts

Not every topic needs the same number. A high-volume clickstream topic may need many partitions, while a small configuration topic needs one or a few. Assigning a large default count to all topics wastes resources and adds to the cluster-wide total. Set counts per topic, according to its own throughput and consumer needs.

Topic typeSizing guidanceReason
High-volume eventsSize by throughput and consumer parallelismNeeds parallel producers and consumers
Low-volume eventsA small numberThin batches and idle partitions add cost without benefit
Strict ordering globallyOne partition, or partition by keyOrdering is only kept within one partition
Compacted state topicsModerate, mindful of cleaner loadState rebuild time grows with partition size
Latency-critical pathsEnough to avoid queueing, no moreOverhead hurts the tail

18Measuring Latency Properly

You cannot manage what you cannot measure, and measuring latency across several stages takes some care.

Measure at every stage

A single end-to-end number tells you that latency changed but not why. Stage-by-stage measurements tell you where to look. Kafka exposes many metrics on producers, brokers, and consumers, and most of the useful ones are grouped below by where they sit in the journey.

StageWhat to look atWhat a rise suggests
ProducerRecord queue time, batch size average, request rate, buffer availableThin batches, buffer pressure, too many partitions for the traffic
Broker requestRequest time broken into queue, local, remote, response queue, and send partsWhich step in the broker is slow
ReplicationIn-sync replica shrinks and expansions, follower lag, fetcher lagOverloaded fetchers or slow followers
Broker threadsRequest handler idle percentage, network processor idle percentageThread saturation
ConsumerFetch latency, records per request, lag per partition, poll intervalFetch tuning issues, slow processing, hot partitions
GroupRebalance count, rebalance duration, time since last rebalanceMembership instability or expensive assignments
ClusterController event queue time, under-replicated and offline partitionsControl plane pressure, failing brokers

The broker request time breakdown

For each request type, the broker reports where time was spent. The parts are the wait in the request queue, the local processing, the wait for remote replication, the wait in the response queue, and the time to send the response. This breakdown is one of the most useful tools for our topic. A large remote part on produce requests points at replication. A large request-queue part points at not enough handler threads or too many requests, often from small batches. A large local part points at disk or CPU.

flowchart LR
    A["Request arrives"] --> B["Request queue wait"]
    B --> C["Local processing and log append"]
    C --> D["Remote wait for followers"]
    D --> E["Response queue wait"]
    E --> F["Response send time"]
    F --> G["Client receives answer"]
        
FIG 10 — The broker’s request time breakdown shows which step is responsible for extra delay

Use the picture as a checklist. When produce latency rises after adding partitions, look at each box in turn. If the queue wait rose, requests are arriving faster than threads can handle them. If the remote wait rose, followers are late. Each answer leads to a different fix.

Measuring end-to-end delay

The simplest method is to put a creation timestamp in each test message and compare it with the time the consumer receives it. This requires clocks that are well synchronized between the producer and consumer machines, or, even better, using the same machine for both during tests. Another method is to use consumer lag expressed in time rather than in message counts. Lag in messages is easier to collect but says little about delay unless you know the rate.

Running a fair experiment

1

Fix everything except the partition count

Use the same hardware, message size, key distribution, and client settings for each run.

2

Use a realistic rate and pattern

Send at the rate you expect in production, including bursts, and include realistic keys.

3

Warm up, then measure for long enough

Ignore the first minutes while caches fill, then run long enough to capture rare events.

4

Record percentiles per stage

Save the median, ninety-ninth, and maximum for each stage, not just the average total.

5

Test failure too

Stop a broker on purpose and record how long the disturbance lasts at each partition count.

i
Use the Tools That Ship With Kafka

Kafka includes performance test tools for producers and consumers, and an end-to-end latency test tool. They are a good start for comparing partition counts, though they may not match your real traffic, so follow up with a test that uses your real message shapes.

19Tuning Levers to Offset Partition Costs

If you need many partitions, several settings and design choices reduce the price you pay for them.

Producer levers

The producer’s job is to keep batches useful even when traffic is spread thin. Raising the linger time gives batches longer to fill, at the cost of a small guaranteed wait. Raising the batch size allows fuller batches when traffic is heavy. Compression works better on larger batches, so it rewards the first two levers. For keyless traffic, the sticky partitioner concentrates records on one partition at a time, which fills batches quickly and rotates for balance.

Simple Analogy

A school bus that leaves the instant one child boards makes many trips with one child each. A bus that waits five minutes fills with a dozen children and makes fewer trips. The children wait a little longer at the stop, but the road is much less crowded and everyone arrives sooner overall when the road is the problem.

Broker levers

On the broker, the most helpful settings are the number of replica fetcher threads, the number of network threads, the number of request handler threads, and the number of recovery threads per data directory. Each raises capacity at a cost of extra CPU or memory, so change them step by step and watch the thread idle metrics. Spreading data across several disks helps with scattered writes. Keeping leadership balanced avoids overloading one broker.

LeverWhereHelps withCost or risk
Longer linger timeProducerThin batches, high request rateAdds a fixed wait to each message
Larger batch sizeProducerFewer requests for busy partitionsMore memory per open batch
Larger buffer memoryProducerSend calls blockingMore memory in the application
CompressionProducerNetwork and disk volumeCPU use, works best with larger batches
More replica fetchersBrokerLong follower roundsMore CPU and connections
Follower fetch wait tuningBrokerResponsiveness of replicationMore requests when set very short
More network and I/O threadsBrokerRequest queue waitsDiminishing returns, CPU contention
More recovery threadsBrokerSlow restartsHeavier disk use during start
More brokersClusterToo many partitions per brokerCost and operational effort
Rebalance-friendly assignmentConsumerLong pausesNeeds compatible client versions
Fetch size tuningConsumerChatty or slow fetchesMemory use grows with partitions owned

Design levers

Design 1

Share topics

Use keys within a shared topic instead of one topic per tenant, so the cluster-wide partition total stays moderate.

Design 2

Split hot keys

Spread a very busy key over several sub-keys so that it can use several partitions.

Design 3

Separate workloads

Give latency-critical topics their own brokers or a separate cluster so that bulk topics with many partitions do not disturb them.

Design 4

Keep processing parallel inside a consumer

When processing is the bottleneck, a consumer can hand work to a pool of threads, which reduces the need for extra partitions, provided that ordering and commit handling are done carefully.

flowchart TD
    A["Latency too high after adding partitions"] --> B{"Which stage grew?"}
    B -->|"Producer queue time"| C["Raise linger and batch size, check buffer memory"]
    B -->|"Broker remote wait"| D["Add replica fetchers, balance leaders, check followers"]
    B -->|"Broker request queue"| E["Reduce request count, add threads or brokers"]
    B -->|"Consumer lag"| F["Add consumers up to the partition count, tune processing"]
    B -->|"Rebalance pauses"| G["Use cooperative assignment and static membership"]
    B -->|"Failover time"| H["Reduce partitions per broker, review controller design"]
        
FIG 11 — Each stage that grows points to a specific family of fixes

The diagram is a map from symptoms to remedies. Start at the top with the observation that latency rose. Identify which stage grew using the measurements from the previous chapter, and then follow the matching branch. Trying all remedies at once makes it impossible to know which one worked.

i
Change One Thing at a Time

Every lever has side effects. Adjust one setting, measure for long enough to see rare events, and record the result. A slower and calmer method usually finishes sooner than a fast and confusing one.

20Anti-Patterns: Common Mistakes With Partition Counts

Most partition problems come from a small set of habits, and knowing them makes them easy to avoid.

ANTI-PATTERN-01 Avoid
Problem

Giving every topic a very large default partition count “just in case.”

Why It’s Harmful

Small topics end up with thin batches, idle partitions, and open files, and the cluster-wide total grows until failover, restarts, and metadata all slow down. The cost is paid every day for a benefit that may never be needed.

Correct Approach

Size each topic from its own throughput and consumer needs, add sensible headroom, and review the total per broker regularly.

ANTI-PATTERN-02 Avoid
Problem

Treating too few partitions as safe and ignoring consumer parallelism.

Why It’s Harmful

With slow processing and few partitions, only a few consumers can work. The backlog grows and end-to-end latency becomes very high, even though the brokers are nearly idle.

Correct Approach

Compute the number of parallel consumers you need and make sure the count is at least that large.

ANTI-PATTERN-03 Avoid
Problem

Adding partitions to a keyed topic in production without planning for the change in key mapping.

Why It’s Harmful

Keys begin to map to new partitions, per-key ordering is broken across the change, and stateful consumers may hold history in one place and receive new events in another.

Correct Approach

Choose the count with future growth in mind, and if a change is unavoidable, plan a migration to a new topic or a controlled window in which the reshuffle is safe.

ANTI-PATTERN-04 Avoid
Problem

Judging success by average latency only.

Why It’s Harmful

Partition overhead shows up first in the tail. The average looks healthy while the slowest messages, which cause customer-visible delays, keep getting worse.

Correct Approach

Track the median and high percentiles at every stage, and set targets on percentiles.

ANTI-PATTERN-05 Avoid
Problem

Raising partition counts without reviewing producer and consumer settings.

Why It’s Harmful

Buffers, batch sizes, and fetch limits tuned for the old shape of traffic may now be far too small or too large, causing blocking sends, thin batches, or memory pressure.

Correct Approach

Treat a partition change as a change to the whole pipeline, and retest the clients along with the brokers.

ANTI-PATTERN-06 Avoid
Problem

Creating one topic per customer, device, or event type at large scale.

Why It’s Harmful

The cluster-wide total of partitions grows without any single topic looking large, and the control plane, failover, and restarts suffer.

Correct Approach

Use shared topics with keys, and reserve dedicated topics for cases with genuinely different requirements.

ANTI-PATTERN-07 Avoid
Problem

Ignoring operating system limits until a broker fails.

Why It’s Harmful

File descriptor and memory map limits produce sudden failures, not gentle slowdowns, and they often appear during a restart when the pressure is highest.

Correct Approach

Set generous limits from the beginning and alert when usage passes a comfortable share of them.

ANTI-PATTERN-08 Avoid
Problem

Assuming more partitions can fix a hot key.

Why It’s Harmful

A single key always lands on one partition, so extra partitions stay idle while the hot one queues up.

Correct Approach

Redesign the key, split it into sub-keys, or handle the hot key with a dedicated path.

21Worked Scenarios

These illustrative stories are invented for teaching. They show how the ideas of the earlier chapters combine when you face a real symptom.

Scenario 1: The backlog that would not shrink

A team processes order events with a topic of six partitions. Each event needs a slow call to another service, so a consumer handles only a small number of events per second. The brokers are almost idle, but the backlog keeps growing and end-to-end delay is measured in minutes. The cause is parallelism: only six consumers can work. Raising the partition count to a value that matches the required number of parallel consumers, with a review of key mapping, cuts the delay dramatically. This is the left side of the U-curve.

Scenario 2: The topic with far too many lanes

A quiet topic with a few messages per second was created with hundreds of partitions. Producers with a short linger time send a tiny batch for nearly every message, so the request rate is high, and the brokers spend time on tiny requests. Cutting the partition count in a new topic, or raising the linger time modestly, reduces request rate and lowers latency. This is the right side of the U-curve for a low-traffic topic.

Scenario 3: The slow recovery after a crash

A cluster with brokers that each lead a very large number of partitions loses one broker. Detection is quick, but electing new leaders and spreading the news takes long, and clients see errors for an extended period. The team reduces partitions per broker by adding brokers, balances leadership, and reviews its controller design. The next crash test shows a much shorter disturbance.

Scenario 4: The deployment that freezes the pipeline

A stream processing application with a large partition count and large local state is redeployed one instance at a time. Each restart triggers a rebalance and a state restore, and latency spikes for many minutes. Static membership, cooperative assignment, and standby replicas shorten the disturbance, and slower, better-planned rollouts avoid overlapping restarts.

Scenario 5: The mystery p99

After doubling the partitions, the average latency is unchanged, but the ninety-ninth percentile is twice as high. Investigation shows that produce requests now carry sections for far more partitions, and short disk bursts delay whole requests. More replica fetchers, balanced leaders, and a separate disk for the busiest topics bring the tail back down.

flowchart TD
    A["Symptom: high end-to-end latency"] --> B{"Is consumer lag large while brokers are idle?"}
    B -->|"Yes"| C["Parallelism shortage: more partitions and consumers"]
    B -->|"No"| D{"Are batches tiny and request rate high?"}
    D -->|"Yes"| E["Too many partitions for the traffic: tune linger or reduce count"]
    D -->|"No"| F{"Is remote wait or follower lag high?"}
    F -->|"Yes"| G["Replication load: more fetchers, balance leaders"]
    F -->|"No"| H{"Do spikes align with restarts or membership changes?"}
    H -->|"Yes"| I["Rebalance or recovery cost: cooperative assignment, fewer partitions per broker"]
    H -->|"No"| J["Look at hot keys, disk, garbage collection, and network"]
        
FIG 12 — A simple decision path from a latency symptom to its most likely partition-related cause

The decision path asks four questions in order, from the most common cause to the least. It is not a substitute for measurement, but it gives you a sensible order in which to look, and it stops you from adding partitions when the real problem is elsewhere.

22Frequently Asked Questions

Q1Do more partitions always increase latency?

No. When work is queuing because of too little parallelism, more partitions reduce latency. Beyond the sweet spot, overhead grows and latency rises. The effect depends on your traffic, hardware, and settings.

Q2Do more partitions always increase throughput?

Throughput rises with parallelism until another limit, such as disk, network, or CPU, is reached. After that, extra partitions add only overhead.

Q3What is the biggest single latency cost of many partitions?

It depends on your setup, but the most common are thin producer batches for low-traffic topics, replication rounds on busy brokers, and slow failover and rebalances at very high totals.

Q4How many partitions can one broker handle?

Guidance in the past was in the range of a few thousand partition replicas per broker for classic setups, with higher numbers possible in newer versions using the built-in metadata quorum. Treat it as an order of magnitude and test on your own hardware and version.

Q5Can I reduce the number of partitions later?

No, Kafka only allows increasing the count of an existing topic. To reduce it, create a new topic and migrate data and clients.

Q6What happens to ordering if I add partitions?

For keyed messages, the key-to-partition mapping changes, so new messages for a key may go to a different partition than older ones, and ordering across the change is not guaranteed.

Q7Why does a low-traffic topic get slower with more partitions?

Because each partition gets fewer messages, batches stay small and wait for the linger time, so requests are more numerous and each message may wait for its batch timer.

Q8How does the number of consumers relate to partitions?

In one group, each partition is read by at most one consumer, so the partition count is the ceiling on useful consumers. Extra consumers stay idle.

Q9Does replication factor matter for this topic?

Yes. Each partition has several replicas, and all replicas count toward broker load. A higher replication factor multiplies the number of logs and the replication traffic.

Q10Do newer Kafka versions change the guidance?

Yes. Improvements such as incremental fetch sessions and the built-in metadata quorum raise practical limits and speed up failover. Always check the documentation for the version you run.

Q11Which acknowledgment setting is least affected by partition count?

Settings that do not wait for replication show the smallest effect on the producer’s send time, but they trade away safety, and consumers still wait for replication before they can see the data.

Q12Should I use a separate cluster for latency-critical topics?

It is a reasonable choice when bulk topics with many partitions would disturb critical ones. Separate brokers or clusters isolate the effects of heavy traffic and large metadata.

Q13How do I find the sweet spot?

Estimate the count from throughput, add headroom, then run load tests at that count and a step above and below while recording percentile latency at each stage. Pick the count at the flat bottom of the curve.

Q14Can I use fewer partitions and more threads inside each consumer?

Yes, if processing is the bottleneck. A consumer can hand messages to a pool of workers, but it must handle ordering and offset commits carefully so that messages are not lost or committed too early.

Q15Why does my restart take so long?

A broker with many partitions has many logs to open and check, especially after an unclean shutdown. More recovery threads and clean shutdowns help.

23Summary and Key Takeaways

Partitions are Kafka’s lanes. Too few lanes create traffic jams, because work queues up behind a parallelism limit. Too many lanes create overhead: thin producer batches, longer replication rounds, heavier metadata, slower rebalances, and slower recovery. Latency therefore follows a U-shaped curve, with a sweet spot that depends on message rate, hardware, cluster size, settings, and software version.

The way forward is not to memorize a number but to follow a method: size from throughput, add headroom, check per-broker totals including replicas, measure percentiles at every stage, test failures, and tune one lever at a time. Watch the tail, watch the operating system limits, and remember that changing the count later disturbs keyed data.

Key Takeaways

  • The relationship is a U-shape — more partitions cut latency while parallelism is the bottleneck and raise it once per-partition overhead dominates.
  • Consumers set the floor — the partition count is the ceiling on useful consumers in a group, so slow processing needs enough partitions to run in parallel.
  • Producers pay per partition — batches are kept for each partition, so spreading light traffic over many partitions makes thin batches and more requests.
  • Replication and control plane costs grow with the total — follower fetch rounds, metadata updates, rebalances, and failover all lengthen as partitions per broker increase, so count replicas and check the cluster-wide total.
  • Judge by the tail, not the average — requests touching many partitions are as slow as the slowest section, so track high percentiles at each stage and test failures.
  • The choice is nearly one-way — partitions can be added but not removed, and adding them changes key mapping, so plan growth up front without over-provisioning.
  • Measure, then tune one lever at a time — use throughput math for a first estimate, load test around it, and use the symptom-to-remedy map to pick the fix.