---
title: "Kafka idempotent producer: retrying NOT_ENOUGH_REPLICAS"
description: "With the ISR below min.insync.replicas, acks=all fails. The idempotent Kafka producer retries until a broker returns, then the record commits exactly once."
url: https://monedula.dev/kafka-simulator/scenarios/idempotence-retry/
---

# Kafka idempotent producer: retrying NOT_ENOUGH_REPLICAS

Scenario 01.3.1 · Idempotence retry. Producers & EOS · Intermediate · about 2 min · Apache Kafka 4.3.

An idempotent acks=all produce retries through NotEnoughReplicas and commits exactly once.

Run it: https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1

## What you start with

With two brokers down the ISR is below min.insync.replicas, so an acks=all produce is rejected with NOT_ENOUGH_REPLICAS. NOT_ENOUGH_REPLICAS is retriable, so the producer retries with backoff within delivery.timeout.ms, and idempotence keeps those retries free of duplicates; once a broker restarts and the ISR recovers the write commits exactly once.

## Step by step

1. **Cluster ready - acks=all, idempotence on** (t+0.000s) [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1&t=0)
2. **Two brokers down - ISR shrinks to 1 (below min.ISR)** (t+5.100s) [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1&t=1)
3. **Produce hits NotEnoughReplicas - retrying** (t+7.100s): NOT_ENOUGH_REPLICAS is retriable, so the producer keeps retrying; idempotence makes each retry safe. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1&t=2)
4. **broker-2 back - the in-flight retry commits exactly once** (t+8.300s): No duplicate: the same record lands at offset 0 once the cluster heals. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1&t=3)
5. **Stable - record committed at offset 0** (t+10.000s) [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.1&t=4)

## The takeaway

An idempotent acks=all producer turns a transient NOT_ENOUGH_REPLICAS into a safe retry: the record commits once the ISR heals, with no loss and no duplicate.

## Configs in this scenario

- [`acks`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_acks): How many replicas must have a write before the producer counts it as sent: 0 (none), 1 (the leader only) or all (every in-sync replica, the default, and required for idempotence). [How acks works](https://monedula.dev/kafka-simulator/configs/acks/)
- [`min.insync.replicas`](https://kafka.apache.org/43/configuration/topic-configs/#topicconfigs_min.insync.replicas): The fewest in-sync replicas, leader included, that must have a write for an acks=all produce to succeed (default 1); with fewer in the ISR the leader rejects the write with NOT_ENOUGH_REPLICAS. [How min.insync.replicas works](https://monedula.dev/kafka-simulator/configs/min-insync-replicas/)
- [`delivery.timeout.ms`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_delivery.timeout.ms): The upper bound on reporting success or failure after send() returns, covering the wait in a batch, the wait for the acknowledgement and every retry (default 120000, 2 minutes); it should be at least request.timeout.ms plus linger.ms.

## Further reading

- [Apache Kafka documentation](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_enable.idempotence)

## Troubleshooting

- [NotEnoughReplicasException in Kafka: causes and fixes](https://monedula.dev/kafka-simulator/troubleshooting/not-enough-replicas/)
