skip to content

Fetch From Follower and Cross-Region Reads

Letting consumers read from a rack-local follower to cut cross-zone traffic. Interviewers like it as a cost question: the same design, a much smaller egress bill.

part ofApache Kafkaoverview, primer and where to startread it →
on this pageshow

questions

5

What is 'fetch from follower' in Kafka (KIP-392), and what problem does it solve in a multi-AZ or multi-region deployment?

level: juniorimportance: must knowfreq 70%

answer

  1. KIP-392, Kafka 2.4
  2. read from same-AZ follower, write still to leader
  3. broker.rack + client.rack + RackAwareReplicaSelector
  4. kills cross-AZ egress cost
  5. reads up to follower high-watermark

basics

~20 s

Normally Kafka consumers read only from the partition leader. Fetch-from-follower (KIP-392) lets a consumer read from a nearby replica (follower) in its own availability zone instead, cutting cross-zone network traffic and the cloud egress cost that comes with it.

solid answer

~40 s

Before KIP-392 (Kafka 2.4), all reads went to the partition leader. In a cloud cluster spread across availability zones (AZs), a consumer often sat in a different AZ from the leader, so every fetched byte crossed an AZ boundary — and cloud providers bill cross-AZ traffic. KIP-392 lets a consumer fetch from a follower replica that lives in the same AZ. You enable it broker-side with replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector and tag each broker with broker.rack; the consumer sets client.rack to its own AZ. The broker then returns the 'closest' replica (matching rack) in the fetch response, and the consumer redirects its fetches there. Writes still go only to the leader; only reads move. This keeps the leader single-region/AZ while reads stay local.

go deeper

for a junior

Know the one-liner: consumers can read from a nearby replica to save cross-AZ network cost; writes still go to the leader.

for a middle

Be able to name the three configs (broker.rack, client.rack, replica.selector.class) and that it arrived in Kafka 2.4.

for a senior

Explain the high-watermark bound, ISR eligibility, fallback to leader, and that it's a cost (egress) optimization not a write-path change.

for a principal

Frame it within a cost-optimized multi-AZ topology and contrast with cross-cluster replication; reason about lag/consistency trade-offs.

## The setup Kafka stores each topic partition as a set of **replicas**: one **leader** and several **followers**. A replica is just a copy of the partition's log on a broker. The leader handles all reads and writes; followers continuously copy (replicate) the leader's log so they can take over if the leader dies. An **availability zone (AZ)** is an isolated datacenter within a cloud region. A Kafka cluster is usually spread across multiple AZs (e.g., 3) so the loss of one AZ doesn't take down the cluster. Cloud providers (AWS/GCP/Azure) charge money for network traffic that crosses an AZ boundary — this is **cross-AZ egress cost**. ## The problem before KIP-392 Historically a Kafka consumer could only read from the **leader** of a partition. The leader for a given partition lives on exactly one broker in one AZ. If your consumer runs in AZ-a but the leader is in AZ-b, every single byte the consumer reads crosses the AZ boundary and gets billed. For a high-throughput pipeline this cross-AZ read traffic can dominate the cloud bill. ## What KIP-392 added (Kafka 2.4, Dec 2019) KIP-392 introduced **fetch from follower (FFF)**: a consumer may read from a *follower* replica instead of the leader, as long as the follower is 'closer' to the consumer. Closeness is defined by **rack** — a label (typically the AZ name) attached to each broker and each consumer. The moving parts: - **`broker.rack`** — a broker config; set it to the broker's AZ (e.g. `eu-west-1a`). - **`replica.selector.class`** — a broker config naming the pluggable selector. Default is `LeaderSelector` (read from leader, old behavior). Set it to `org.apache.kafka.common.replica.RackAwareReplicaSelector` to enable rack-aware FFF. - **`client.rack`** — a consumer config; set it to the consumer's own AZ. ## How a fetch resolves 1. The consumer issues a Fetch (or, on metadata, an OffsetsForLeaderEpoch flow) and includes its `client.rack`. 2. The broker runs the configured `ReplicaSelector.select(...)`. `RackAwareReplicaSelector` picks, among the in-sync replicas, one whose `broker.rack` matches the consumer's `client.rack`; if there's a match it returns that follower, otherwise it falls back to the leader. 3. The selected replica is communicated back to the consumer (in the fetch metadata / `preferredReadReplica`), and the consumer routes subsequent fetches for that partition to that follower. ## What does and does NOT move - **Reads** can move to a same-AZ follower → local, cheap traffic. - **Writes (produce)** always go to the **leader** — unchanged. KIP-392 is read-only. - The **leader can stay in a single AZ/region**; only consumers get locality. This is why it fits 'leaders single-region, reads cross-region/AZ-local' designs. ## Important caveats - A consumer only sees data a follower has actually replicated, so it can only read up to the follower's **high-watermark**; if the follower lags, reads can be slightly behind. Correctness (no reading uncommitted data) is preserved because the high-watermark is the committed boundary. - Followers must be **in-sync** (in the ISR) to be eligible. - This is distinct from cross-cluster replication (MirrorMaker 2): FFF is locality *within one cluster*, not copying data between clusters.

  • Does fetch-from-follower change where produces go?
    No. Producers always write to the leader. KIP-392 only redirects consumer reads; the write path and the leader's single location are unchanged.
  • Why is this primarily a cost feature rather than a performance feature?
    The leader can serve reads just fine; the motivation is avoiding cloud cross-AZ/cross-region egress charges by keeping read traffic local. Latency may improve slightly but cost reduction is the headline.

saying these in an interview costs you the question

  • Saying produces can also go to a follower — only reads move.
  • Claiming it replicates data between separate clusters — that's MirrorMaker, not FFF.
  • Thinking it removes the leader entirely or makes it multi-region.

context

open as a page

Walk through the exact configuration needed to enable rack-aware fetch-from-follower, and explain what each setting does.

level: middleimportance: must knowfreq 65%

basics

~20 s

On every broker set broker.rack to its AZ and set replica.selector.class to RackAwareReplicaSelector. On every consumer set client.rack to its own AZ. The broker then matches client.rack to broker.rack and points the consumer at a same-AZ follower.

open as a page

When a consumer reads from a follower (KIP-392), what is the upper bound on the data it can read, and what consistency/lag implications does that create?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A follower can only serve records up to its own high-watermark — the committed offset it has replicated and acknowledged. If the follower lags the leader, the consumer reads slightly older data, and end-to-end latency can grow, though it never reads uncommitted records.

open as a page

You run a 3-AZ Kafka cluster on AWS and your bill is dominated by cross-AZ data transfer from consumers. As a principal engineer, how do you design a fetch-from-follower rollout to actually capture the savings, and what can undermine them?

level: principalimportance: should knowfreq 35%

basics

~20 s

Tag brokers with broker.rack=AZ, enable RackAwareReplicaSelector, ensure every partition has a replica in each consumer AZ (rack-aware placement), and set each consumer's client.rack to its AZ. Savings collapse if there's no in-rack replica, racks are misconfigured, or consumers fall back to the leader.

open as a page

What is the ReplicaSelector interface, and how could you implement a custom replica selector beyond RackAwareReplicaSelector?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

replica.selector.class plugs in a class implementing org.apache.kafka.common.replica.ReplicaSelector. Kafka ships LeaderSelector (default) and RackAwareReplicaSelector. You can write your own select() logic — e.g., choose by latency or a custom topology — returning the replica the consumer should read from.

open as a page