How do acks=all and min.insync.replicas work together to provide durability, and how would you configure them with a replication factor of 3?
answer
- acks=all → wait for whole ISR
- min.insync.replicas → ISR floor for a write
- RF=3, MISR=2, acks=all = tolerate 1 loss
- ISR<floor → NotEnoughReplicas error
- acks=all alone can degrade to 1 copy
basics
~20 sacks=all makes the producer wait until all in-sync replicas have the record. min.insync.replicas sets how many replicas must be in sync for that write to be allowed. With replication factor 3, set min.insync.replicas=2 and acks=all so you can lose one broker without losing data and without halting writes.
solid answer
~40 sThe two settings are complementary. `acks=all` (producer side) tells the leader to wait for all current in-sync replicas (ISR) before acknowledging. `min.insync.replicas` (broker/topic side) defines the floor: if the ISR has fewer than that many members, the leader rejects acks=all writes with `NotEnoughReplicasException`/`NotEnoughReplicasAfterAppendException` instead of acknowledging a write that wouldn't be safely replicated. Used alone, acks=all would happily acknowledge a write even when the ISR has shrunk to just the leader — min.insync.replicas prevents that silent loss of redundancy. The standard durable config with replication.factor=3 is acks=all + min.insync.replicas=2: it tolerates one broker failure (2 replicas still in sync, writes continue) while guaranteeing every acknowledged record is on at least 2 brokers. Add enable.idempotence=true to avoid duplicates on retries. Setting min.insync.replicas=3 with RF=3 maximizes safety but makes any single broker outage block writes.
go deeper
Know acks=all waits for replicas and min.insync.replicas sets how many must be in sync; RF=3 + min.insync=2 + acks=all is the safe combo.
Explain why both are needed together and how the canonical config tolerates one broker loss.
Reason about the consistency-vs-availability behavior when the ISR shrinks and the trade-offs of min.insync.replicas=3.
Set fleet-wide topic defaults, weigh availability impact of high min.insync.replicas, and combine with idempotence/transactions for end-to-end guarantees.
## The two halves **`acks=all` (producer config, also written `acks=-1`)**: the leader will not acknowledge the produce request until **all in-sync replicas** have appended the record. (With `acks=1` only the leader needs it; with `acks=0` the producer doesn't wait at all.) **`min.insync.replicas` (broker default `min.insync.replicas`, or per-topic override)**: the minimum number of replicas that must be **in sync** for an `acks=all` write to be accepted. If the **in-sync replica set (ISR)** drops below this number, the leader refuses the write and returns an error (`NotEnoughReplicasException` before append, `NotEnoughReplicasAfterAppendException` after). ## Why you need both Suppose replication.factor=3 and you only set `acks=all`. If two followers fall behind and get removed from the ISR, the ISR is just `{leader}`. `acks=all` would then acknowledge a write replicated to **one** broker — you've silently lost your redundancy without knowing it. If that one broker then dies, the data is gone. `min.insync.replicas=2` closes this hole: once the ISR shrinks to 1, the broker **rejects** the write rather than acknowledging an unsafe one. The producer gets an error and can retry/alert, but it will never receive a false "durable" acknowledgement. So: **acks=all** decides *whether the producer waits for the ISR*; **min.insync.replicas** decides *how big the ISR must be for that wait to count as durable*. Both are required — acks=all without a sane min.insync.replicas can degrade to single-copy durability. ## The canonical config (RF=3) | Setting | Value | Effect | |---|---|---| | replication.factor | 3 | 3 copies of each partition | | min.insync.replicas | 2 | at least 2 in-sync copies required to accept a write | | acks | all | producer waits for all ISR members | | enable.idempotence | true | de-duplicates retried writes (exactly-once-ish per producer) | This tolerates **one** broker failure: the ISR is still {2 brokers} ≥ 2, so writes continue, and every acknowledged record is on ≥2 brokers. Lose a second broker and writes are rejected (ISR=1 < 2) — Kafka chooses **consistency over availability** here, refusing to accept writes it can't safely replicate. ## Trade-offs - **min.insync.replicas=3 with RF=3**: every write needs all three; maximum durability but **zero** tolerance for a broker being down — any single outage halts writes. - **min.insync.replicas=1**: effectively no protection beyond the leader; not recommended for durable topics. - The setting only bites when combined with `acks=all`; with `acks=1`/`acks=0` it's ignored, because the producer isn't waiting for the ISR anyway. ## Common gotcha People set `acks=all` and think they're safe, leaving `min.insync.replicas=1` (an old default). Under follower lag, that silently degrades to single-copy durability. Always set both together.
- What happens to producers when the ISR drops below min.insync.replicas?acks=all writes are rejected with NotEnoughReplicasException (or NotEnoughReplicasAfterAppendException). Kafka favors consistency over availability — it stops accepting writes it can't safely replicate, and the producer must retry once the ISR recovers.
- Why is acks=all with min.insync.replicas=1 risky even though both are 'set'?If followers fall out of the ISR, acks=all can acknowledge a write replicated to only the leader, silently dropping redundancy. If that broker then fails, acknowledged data is lost. You need min.insync.replicas≥2 to guarantee multiple copies.
saying these in an interview costs you the question
- Saying acks=all alone guarantees durability regardless of min.insync.replicas.
- Setting min.insync.replicas=3 with RF=3 without noting that any single broker outage then blocks writes.
- Thinking min.insync.replicas matters when acks is 1 or 0 — it only applies to acks=all.