How the three modes compare
Key concepts
ISR β In-Sync Replicas
A dynamic set of brokers that have replicated all messages within replica.lag.time.max.ms. For acks=all, every broker in this set must write and confirm. If a follower falls behind, it's removed from ISR.
min.insync.replicas
Works together with acks=all. Sets the minimum ISR size that must be available. E.g. with 3 replicas and min.insync.replicas=2, the cluster can tolerate 1 broker failure without blocking the producer.
The acks=1 silent loss
Leader acks the producer, then crashes before followers replicate. Kafka elects a new leader from the followers β this new leader does not have the message. The producer got an ACK but the message is gone.
Idempotent producer
Set enable.idempotence=true (default in Kafka 3+). Each message gets a sequence ID. Retries won't cause duplicates. Required for exactly-once semantics. Automatically sets acks=all.
acks=all flow
1. Producer β Leader (write to log). 2. Leader β Follower-1 (replicate). 3. Leader β Follower-2 (replicate). 4. Followers ACK leader. 5. Leader ACKs producer. Only then does the producer continue.
Unclean leader election
If unclean.leader.election.enable=true, a lagging broker can become leader β accepting possible data loss. For financial/transactional topics set it to false (default since Kafka 0.11).
ISR membership
Metrics / click-stream ingestion USE acks=0
You're sending millions of analytics events per second. Losing a few events is acceptable. Every millisecond of latency matters. Fire-and-forget gives you the highest possible throughput with minimal broker overhead.
Activity feeds / notification events USE acks=1
A reasonable middle ground. You want reasonable reliability without paying the full cost of ISR acknowledgment on every message. Acceptable for workloads where an occasional message loss on leader crash is tolerable.
Financial transactions / order events USE acks=all
You must not lose a single message. Payments, inventory updates, booking confirmations β any message loss causes real-world problems. Use acks=all with idempotent producer for exactly-once semantics.
Using acks=1 for financial events AVOID
Leader acks your payment, then crashes before replication. A new leader is elected β it never got the message. The payment is silently lost but the producer returned success. Your system believes the payment was recorded.
High-throughput with strong guarantees USE acks=all + tuning
You need both throughput and durability. Tune batching to amortize the ISR ack cost across many messages. linger.ms delays sending slightly to fill batches. Combine with async callbacks instead of blocking .get().