Explain how fetch.min.bytes and fetch.max.wait.ms work together to trade latency for throughput on the consumer.
answer
- broker waits for min.bytes OR max.wait.ms
- min.bytes=1 default -> low latency, many fetches
- raise min.bytes -> fewer/fatter fetches, +throughput
- max.wait.ms = bounded tail latency / idle-topic safety valve
- worst-case added latency ~= fetch.max.wait.ms
basics
~20 sfetch.min.bytes tells the broker not to answer a fetch until it has at least that many bytes ready. fetch.max.wait.ms caps how long it waits for that. Bigger min.bytes = fewer, larger fetches (more throughput, more latency); the wait prevents waiting forever when traffic is low.
solid answer
~40 sWhen a consumer sends a fetch request, the broker holds it until either fetch.min.bytes (default 1) of data is available across the requested partitions, or fetch.max.wait.ms (default 500) elapses — whichever comes first. With min.bytes=1, the broker replies the instant any record exists, giving low latency but many tiny fetches and high request overhead. Raising min.bytes to, say, 100KB makes the broker batch up data, producing fewer, fatter fetches that amortize network/CPU overhead and boost throughput — at the cost of up to fetch.max.wait.ms of added latency on quiet topics. The wait timeout is the safety valve: on a low-traffic partition you don't want the consumer blocked indefinitely waiting to accumulate min.bytes, so after max.wait.ms the broker returns whatever it has, even if below the threshold.
go deeper
Know min.bytes=1 default means low latency; raising it batches data for throughput.
Explain the OR semantics and that max.wait.ms bounds the latency penalty on idle topics.
Pick concrete values per workload (latency-sensitive vs batch) and reason about request overhead amortization.
Set org-wide consumer profiles and explain interactions with compression, fetch.max.bytes, and broker request-handler load.
## The fetch request lifecycle Consumers don't poll the OS for each record; they send **fetch requests** to brokers asking for data from a set of partitions starting at given offsets. Two configs shape how the broker responds: - **fetch.min.bytes** (default **1**): the minimum total bytes the broker should accumulate before answering. - **fetch.max.wait.ms** (default **500**): the maximum time the broker will hold the request waiting to reach fetch.min.bytes. The broker responds when **EITHER** condition is satisfied: enough bytes accumulated, OR the wait time expired. ## The latency/throughput trade-off - **min.bytes = 1 (default):** broker replies as soon as a single byte is available. Lowest latency, but if traffic is bursty/light you get a storm of tiny fetch responses. Each request has fixed overhead (network round trip, broker request handling, decompression setup), so tiny fetches waste CPU and bandwidth. - **min.bytes = large (e.g., 1MB):** broker waits to batch ~1MB before replying. Far fewer requests, each carrying more payload — better throughput and lower broker CPU per byte. But on a slow topic you may now wait up to fetch.max.wait.ms before getting anything. ## Why the wait cap exists Without fetch.max.wait.ms, a consumer on a near-idle partition with min.bytes=1MB could block essentially forever waiting for 1MB to arrive. The wait cap guarantees the broker answers within a bounded time even if the byte threshold isn't met — bounding tail latency. So the **worst-case added latency** of raising min.bytes is roughly fetch.max.wait.ms. ## How they interact with other configs - **fetch.max.bytes / max.partition.fetch.bytes** bound the *upper* size of a response; min.bytes bounds the *lower* trigger. They are independent dials. - High-throughput batch consumers: raise min.bytes (e.g., 50KB–1MB) and accept the latency. - Latency-sensitive (e.g., request/response over Kafka): keep min.bytes=1 and possibly lower max.wait.ms. ## Edge cases - If a single record exceeds fetch.min.bytes, the threshold is trivially met immediately. - Compression: min.bytes is measured on the on-broker (compressed log) bytes, so effective record counts vary with compression ratio. - Idle topics: with default 500ms wait and min.bytes=1, you still get sub-ms responses because 1 byte is almost always available; the wait only matters once min.bytes is raised.
- If you set fetch.min.bytes to 1MB on a topic that gets one small message every few minutes, what latency does a consumer see?Roughly fetch.max.wait.ms (default 500ms). The broker can't reach 1MB, so it waits out the timeout and returns the small message after ~500ms. The byte threshold is never met, so the wait cap governs latency.
- Does raising fetch.min.bytes increase the maximum size of a fetch response?No. The upper bound is fetch.max.bytes (and max.partition.fetch.bytes per partition). fetch.min.bytes only sets the lower trigger for when the broker replies; the two limits are independent.
saying these in an interview costs you the question
- Saying the broker waits for BOTH min.bytes AND max.wait.ms (it's whichever comes first).
- Claiming fetch.min.bytes sets the maximum response size (that's fetch.max.bytes).
- Ignoring that the worst-case latency penalty is bounded by fetch.max.wait.ms.