Skip to content

Acks and Durability

The acks setting decides how many replicas must confirm a write before Kafka calls it durable — trading latency for the guarantee that your record survives a broker failure.

Every partition has one leader replica and zero or more follower replicas. The acks setting controls how many of them must acknowledge a write before the producer considers send() successful. These three values — 0, 1, and all — are the canonical names used across every Kafka client and the official docs:

  • acks=0 — fire-and-forget. The producer does not wait for any acknowledgement; it counts the record as sent the moment it leaves the client. Lowest latency, but a record can be lost silently if the leader is down.
  • acks=1 — leader only. The leader writes the record to its own log and replies. Fast, but if the leader crashes before a follower has replicated that record, the record is lost.
  • acks=all (equivalently acks=-1) — every in-sync replica must confirm. The record is safe as long as one in-sync replica survives. Highest durability, highest latency.
# Fire-and-forget: fastest, weakest guarantee
acks=0
# Leader only: fast, but unreplicated writes can be lost on leader failure
acks=1
# All in-sync replicas must confirm: strongest durability
acks=all

In KafkaJS, acks is not a producer-level property — it is a per-send option you pass to send(), using the same three values:

// -1 = all (the default), 1 = leader only, 0 = fire-and-forget
await producer.send({ topic: 'orders', acks: -1, messages })

acks=all needs min.insync.replicas to mean anything

Section titled “acks=all needs min.insync.replicas to mean anything”

acks=all alone says “all replicas that are currently in sync.” If only the leader is in sync at that moment, “all” is just the leader — and you are effectively back to acks=1. The broker-side min.insync.replicas closes this gap: it sets the minimum number of in-sync replicas that must be available for the write to be accepted at all.

With min.insync.replicas=2 on a topic with replication factor 3, a producer using acks=all needs at least two replicas in sync. If only one is available, the broker rejects the write (a NotEnoughReplicas error) rather than accepting a record that could vanish. That rejection is the point — you would rather fail loudly than lose data quietly.

Putting this together, a durable KafkaJS producer pairs the per-send acks option (or an idempotent producer, which implies acks: -1 internally — the next lesson covers this) with a min.insync.replicas=2 topic:

const producer = kafka.producer({ idempotent: true }) // implies acks: -1 internally
await producer.send({
topic: 'orders', // a topic configured with min.insync.replicas=2 (broker/topic setting)
messages: [{ key: 'order-42', value: JSON.stringify({ amount: 19.99 }) }],
})
flowchart LR
  p["Producer send()"] --> a0["acks=0: no wait, lowest latency"]
  p --> a1["acks=1: leader writes and replies"]
  p --> aa["acks=all: all in-sync replicas confirm"]
  aa --> misr["'min.insync.replicas=2' must be met or write is rejected"]
  misr --> safe["Durable: survives a broker failure"]
Durability climbs from acks=0 to acks=all with min.insync.replicas

There is no free durability. Each stronger acks level adds a network round trip and waits on more machines, so latency rises as the guarantee strengthens. Pick by the cost of losing a record: metrics and logs can often live with acks=1, but orders, payments, and anything you cannot recreate should use acks=all with min.insync.replicas=2.

What does acks=all guarantee compared to acks=1?
Why does acks=all need min.insync.replicas to be meaningful?
With replication factor 3 and min.insync.replicas=2, what happens if only one replica is in sync during an acks=all send?
What is the core tradeoff as you raise the acks level?