introducción
La idempotencia evita ejecutar dos veces el mismo evento cuando hay reintentos, timeouts o fallos de red. En Kafka, el producer idempotente garantiza “no duplicates on the broker” por partición.
Para flujos de dinero o inventario, duplicar un mensaje puede ser fatal (pagar dos veces, descontar stock de más). Activar idempotencia es barato y suele bastar junto con buenas prácticas de consumo.

¿cómo se generan duplicados?
El productor envía, ocurre timeout o se pierde el ACK → reintenta → el broker recibe otra vez el mismo mensaje y lo persiste de nuevo.


¿cómo lo evita kafka?
Con idempotencia, el producer obtiene un Producer ID y asigna un número de secuencia; el broker guarda el último secuencial aceptado y descarta duplicados.

ejemplo práctico: producer idempotente
Config mínima (Java):
Properties p = new Properties();
p.put("bootstrap.servers", "<brokers>");
p.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
p.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
// idempotencia
p.put("enable.idempotence", "true");
p.put("acks", "all"); // requerir confirmación de réplicas
p.put("retries", Integer.toString(Integer.MAX_VALUE));
p.put("max.in.flight.requests.per.connection", "5"); // OK con Kafka >= 1.1
KafkaProducer<String, String> producer = new KafkaProducer<>(p);
Para exactly-once entre varios tópicos/particiones y con escritura a estado externo, usa transacciones:
p.put("transactional.id", "payments-tx-01"); // id único por instancia
KafkaProducer<String, String> txProducer = new KafkaProducer<>(p);
txProducer.initTransactions();
try {
txProducer.beginTransaction();
txProducer.send(new ProducerRecord<>("pagos", key, value));
// ... (otros topics / writes compatibles)
txProducer.commitTransaction();
} catch (Exception e) {
txProducer.abortTransaction();
}demo: idempotencia y reintentos
envía un pago y, con timeout activo, observa el reintento. Con idempotencia=ON el broker ignora el duplicado; con OFFel consumidor termina procesando dos pagos.
patrón de consumo: defensa adicional
Aunque el broker deduplica, es buena práctica que el consumidor tenga una llave idempotente (por ejemplo, eventoId) y registre qué ya procesó, sobre todo si llama APIs o DBs.
// pseudocódigo if (alreadyProcessed(eventoId)) return; process(event); markProcessed(eventoId);


checklist rápido
enable.idempotence=true,acks=all,retries=∞.max.in.flight.requests.per.connection ≤ 5(Kafka >= 1.1).- usa
transactional.idsi necesitas transacciones entre topics/DB. - define clave idempotente de negocio y de-duplicación en el consumidor.
- observabilidad: métricas de reintentos, error rate y DLQ si aplica.