The Kafka producer's acks setting directly controls the trade-off between write durability and latency. The choice is not simply fast vs. slow — it must be made with the relationship between ISR and min.insync.replicas (MinISR) in mind.
This article aligns with the official behaviors commonly tested on the CCDAK (Confluent Certified Developer for Apache Kafka) exam and distills them into practical decision criteria. Version-sensitive details are treated conservatively with explicit cautions.
acks specifies at which stage the producer waits for an acknowledgment after sending. acks=0 waits for nothing, acks=1 waits only for the leader, and acks=all (= -1) waits for ACKs from every ISR (In-Sync Replicas) member. The ISR is the leader plus the set of up-to-date followers, not all assigned replicas.
min.insync.replicas (MinISR) becomes meaningful with acks=all and defines, on the server side, the minimum ISR size required to consider a write successful. For example, on a topic with replication factor 3 and MinISR=2, writing with acks=all succeeds when the ISR has at least 2 members but fails with a NotEnoughReplicas-class error when only 1 remains. This enforces a durability floor at the cost of becoming unwritable under some failure scenarios.
| Setting | Durability | Latency | Availability (RF=3, MinISR=2) |
|---|---|---|---|
| acks=0 | Weakest (treated as success even on non-delivery) | Shortest | High (no waiting, minimal impact) |
| acks=1 | Medium (loss possible right after a leader failure) | Low to medium | High (depends only on the leader) |
| acks=all | Strong (depends on ISR size) | Medium to high (dragged by the slowest ISR member) | OK with ISR>=2, error when ISR<2 |
acks and replication response flow (conceptual diagram)
Producer --> Leader P
|
v
followers: F1, F2
acks=0: P -send-> L (returns immediately) [does not wait for F1/F2]
acks=1: P -send-> L -ACK-> P [replication to F1/F2 is asynchronous]
acks=all: P -send-> L -> F1/F2
^ ^
| |
ACK(F1,F2 in ISR)
\ /
--> L -ACK-> PRelationship of key settings (conceptual notes)
Producer side: acks, retries, delivery.timeout.ms, request.timeout.ms, enable.idempotence
Broker / topic side: replication.factor, min.insync.replicas, unclean.leader.election.enable
Note: acks=all means every ISR member acknowledges. If MinISR cannot be met the producer errors (NotEnoughReplicas, for example).acks=0 treats the send as successful immediately, so the network round-trip is essentially absent from latency. The fundamental risk is that you cannot detect failed delivery to the broker or dropped batches. Increasing retries has limited effect because no error is returned.
It is safer to restrict its use to loss-tolerant telemetry or transient clickstreams. Make sure downstream aggregation is idempotent and estimable, and that the overall design tolerates loss.
| Aspect | Behavior under acks=0 | Operational notes | Alternative |
|---|---|---|---|
| Error detection | Not possible | Only indirect signals like sender-side queue exhaustion are observable | acks=1 or higher |
| Retries | Limited effect | Only effective for pre-send exceptions | Enable with acks=1 or all |
| Ordering | Records are just sent in submission order | Non-delivery on the server side is still treated as success | Lean toward an idempotent design |
Shortest path under acks=0
Producer -> Leader (returns success immediately)
(follower replication does not affect the result)
Failure: the producer never learns about a network break or a leader going downProducer configuration example (acks=0)
props.put("acks", "0");
props.put("linger.ms", 0);
props.put("batch.size", 131072);
props.put("retries", 0); // limited effect
// Use this only where loss is acceptableacks=1 returns an ACK as soon as the leader receives the record and appends it to the log. Because replication to followers is asynchronous, unreplicated data can be lost in a narrow window right after a leader failure. The balance is adequate for many workloads but does not meet strict durability requirements.
Latency tends to be lower than with acks=all and availability is higher, but shrinking the failure window relies on fast follower replication (healthy networking and storage, appropriate load).
| Timing | Leader state | Follower replication | Result |
|---|---|---|---|
| Just after ACK, followers not yet caught up | Up | Incomplete | Subsequent failure may cause loss |
| After followers have caught up | Up | Complete | Leader failover preserves data even on failure |
| Failure before send | Down | None | Client can recover via retries |
Failure window under acks=1 (conceptual timeline)
t0: send -> Leader append -> ACK to Producer
|<--- unreplicated window --->|
followers caught up at t1
A failure in [t0, t1) can lose the unreplicated dataSafer companion configuration example
props.put("acks", "1");
props.put("retries", Integer.MAX_VALUE);
props.put("delivery.timeout.ms", 120000);
props.put("request.timeout.ms", 30000);
// Ordering during retries depends on the client and version. Lower max.in.flight if you need to control itacks=all waits for ACKs from every ISR member. Latency is pulled by the slowest ISR member, but combined with MinISR you can enforce a durability floor of "fail unless replicated to at least N nodes".
When the ISR drops below MinISR, the producer's write fails and the broker may return errors such as NotEnoughReplicas or NotEnoughReplicasAfterAppend. This design accepts reduced availability in exchange for preventing data loss.
| RF | MinISR | Current ISR | Result under acks=all |
|---|---|---|---|
| 3 | 2 | 3 | Success (latency depends on slowest ISR member) |
| 3 | 2 | 2 | Success (just barely allowed) |
| 3 | 2 | 1 | Failure (error because below MinISR) |
acks=all with ISR / MinISR
RF=3, MinISR=2
ISR={Leader, F1, F2}
Case A: ISR=3 -> both F1 and F2 ACK the leader -> L ACKs -> P (success)
Case B: ISR=2 -> only F1 ACKs the leader -> L ACKs -> P (success)
Case C: ISR=1 -> not enough follower ACKs -> error returnedConfiguration on both the topic and the client side
# Set MinISR on the topic
kafka-topics --alter --topic critical-events \
--config min.insync.replicas=2 --bootstrap-server <broker>
# Producer (example)
props.put("acks", "all");
props.put("retries", Integer.MAX_VALUE);
props.put("delivery.timeout.ms", 120000);
props.put("enable.idempotence", true); // when you need strict deduplication
# Note: default values differ by client and version, so check the docs for the version you runBeyond acks, linger.ms and batch.size control the sender-side wait and batching. With many small messages, raising linger modestly to batch records is an effective way to amortize networking and syscall overhead in practice.
delivery.timeout.ms is the overall retry budget, and request.timeout.ms is the wait per request. Compression (compression.type) and appropriate partition counts also affect latency and throughput. Always surface producer-side request-latency and broker-side replica.lag in metrics to continuously validate that your acks choice is appropriate.
| Setting | Primary effect | Side effects / cautions | Application guideline |
|---|---|---|---|
| linger.ms | Increases send wait, improves batch efficiency | Adds latency equal to the wait | Tune starting from 5-20 ms |
| batch.size | Increases data per request | Too large increases wait time | Start around 64-256 KB |
| compression.type | Saves bandwidth, increases CPU usage | Watch for CPU bottlenecks | Compare snappy vs. zstd |
| delivery.timeout.ms | Overall retry budget | Too short leads to premature failures | >= 2 × request.timeout.ms |
Conceptual decomposition of latency
queue (linger) |-> send/wait (RTT round trip) |-> broker processing |-> follower replication (depends on acks)
|----------------- client side ------------------| |------ server side ------|Latency budgeting (rough estimate)
# Example: RTT=5ms, linger=10ms, broker processing=2ms, follower replication=8ms
# acks=0: ~ linger(10) + send (OS/queue) ~= 10-12ms
# acks=1: linger(10) + RTT(5) + processing(2) ~= 17ms
# acks=all: linger(10) + RTT(5) + processing(2) + replication(8) ~= 25ms
# Real numbers move with batching, load, GC and I/O. Correct with metricsOn the CCDAK, classic questions cover the relationship between acks, MinISR, and ISR, the outcomes during failures, and combinations with the idempotent producer and transactions. It is especially important to understand that "acks=all means every ISR member, not every assigned replica" and that "writes fail when ISR drops below MinISR".
In production, it is common to disable unclean.leader.election.enable to avoid data loss. Because defaults and exact behaviors are version-dependent, always confirm against the official documentation for the version running in your environment.
| Scenario | Recommended acks | Additional conditions | Metrics to monitor |
|---|---|---|---|
| Critical events (no loss) | all | RF>=3, MinISR>=2, idempotence enabled | replica.lag, request-latency |
| General workloads (balanced) | 1 | Large retries, monitor delivery delays | failed-requests-rate |
| Loss tolerant, shortest latency | 0 | Compensate via audit design | Send queue backlog, drop rate (downstream) |
Simple decision flow for choosing acks
Loss acceptable? --yes--> acks=0
|
no
v
Availability first, even during an outage? --yes--> acks=1
|
no
v
acks=all (plus MinISR)Configuration templates (by profile)
# Durable (no loss allowed)
acks=all
retries=Integer.MAX_VALUE
delivery.timeout.ms=120000
enable.idempotence=true # add transactions if required
# Balanced (typical business workload)
acks=1
retries=Integer.MAX_VALUE
delivery.timeout.ms=120000
# Ultra-low-latency (loss acceptable)
acks=0
linger.ms=0
batch.size=131072CCDAK
Question 1
A topic has replication factor 3 and min.insync.replicas=2. You need to write critical payment events with minimal loss, and writes must continue even when one broker is taken offline for planned maintenance. Which configuration best meets these requirements?
Correct answer: A
With RF=3 and MinISR=2, taking one broker offline still typically leaves ISR=2, and acks=all confirms replication to at least two nodes before success — meeting the durability/availability balance. B reduces durability; C cannot even detect loss; D loses availability because writes fail the moment ISR drops to 2. Idempotence reinforces deduplication and ordering.
Does acks=all mean writes are completed to ALL replicas?
No. acks=all means ACKs from every member of the ISR (In-Sync Replicas), not all assigned replicas. Lagging followers that have dropped out of the ISR are not part of the condition.
Does acks=all guarantee zero loss even under disk failure?
Not absolutely. Kafka does not force a synchronous fsync per message, so replication is the primary defense against a single-node failure. Combining acks=all with an appropriate MinISR (e.g. 2) ensures success only after the record is replicated to multiple nodes, which raises durability, but the worst-case design risk cannot be reduced to zero.
How do acks relate to the idempotent producer and transactions?
When enabling idempotence or transactions, acks=all is a prerequisite (or the client automatically configures equivalent behavior). The exact defaults and constraints depend on the client and version, so verify the official documentation for the Kafka/Confluent client you are using.
Practice with certification-focused question sets
Try free questionsNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Kafka Topics & Partitions: Distribution Fundamentals (2026)
How Kafka topics and partitions enable scale — ordering guar...
CCDAK Exam Guide: Confluent Certified Developer (2026)
Complete prep for the CCDAK exam — Producer/Consumer API, St...
CCAAK Exam Guide: Confluent Certified Administrator (2026)
Pass the CCAAK exam — cluster management, partitions, securi...
Kafka Replicas & ISR: Fault Tolerance Explained (2026)
Replica placement, in-sync replicas (ISR), leader election. ...
Kafka Offsets: Commit Modes & Consumer Position (2026)
Offset semantics — auto vs. manual commit, __consumer_offset...