Kafka
Spring Kafka
Idempotence
Producer Configuration
Message Brokers

Spring Kafka Idempotence Producer configuration

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Apache Kafka is a distributed event-streaming platform capable of handling trillions of events a day. Initially conceived as a messaging queue, Kafka is based on an abstraction of a distributed commit log. When working with Kafka to produce messages, ensuring that each message is processed exactly once becomes paramount—especially in systems where duplicate processing can lead to inaccurate data or repeated side effects. In Kafka, enabling idempotence in the producer ensures that messages are delivered exactly once to a particular partition during a single producer session.

What is an Idempotent Producer?

An idempotent producer is capable of producing messages securely in such a way that even in the event of network errors leading to retries, no duplicates are written to the Kafka log. Kafka ensures idempotence by assigning a sequence number to each message and the broker keeps track of these sequence numbers to avoid duplicates.

Configuration of an Idempotent Producer

To configure a producer application in Spring Kafka for idempotence, you primarily need to update the producer's settings. Here’s how you can achieve that:

  1. Enable Idempotence: Set the enable.idempotence configuration to true. This tells Kafka to ensure that exactly one copy of each message is written to the log.
  2. Producer Acknowledgements (acks): Set this to all to ensure that the producer receives a successful acknowledgment from all replicas of the partition leaders. This is crucial to guarantee the durability and robustness of message delivery.
  3. Retries and Max In-Flight Requests: Since Kafka 0.11, supporting idempotence requires managing in-flight requests and retries. You should set max.in.flight.requests.per.connection to 5 or less to maintain order guarantee while enabling retries by setting retries to a higher number or even to Integer.MAX_VALUE for practically unlimited retries.

Here is an example configuration for a Spring Kafka application:

java
1import org.springframework.kafka.core.DefaultKafkaProducerFactory;
2import org.springframework.kafka.core.KafkaTemplate;
3import org.springframework.kafka.support.serializer.JsonSerializer;
4import java.util.HashMap;
5import java.util.Map;
6
7public KafkaTemplate<String, Object> kafkaTemplate() {
8    Map<String, Object> configs = new HashMap<>();
9    configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
10    configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
11    configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
12    configs.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true);
13    configs.put(ProducerConfig.ACKS_CONFIG, "all");
14    configs.put(ProducerConfig.RETRIES_CONFIG, Integer.MAX_VALUE);
15    configs.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, 5);
16
17    return new KafkaTemplate<>(new DefaultKafkaProducerFactory<>(configs));
18}

Why Idempotence Matters

Idempotence in Kafka reduces the complexity of your application by handling duplicate messages seamlessly. It is especially beneficial in scenarios where exactly-once processing is critical, such as financial transactions or stateful computations.

Summary Table

Here's a summary of key configurations for an idempotent producer in Kafka:

Configuration KeyRecommended ValueDescription
enable.idempotencetrueEnables idempotent production by the Kafka producer.
acksallWaits for the full set of in-sync replicas to acknowledge the messages.
retriesInteger.MAX_VALUEAllows unlimited retries to prevent data loss.
max.in.flight.requests.per.connection5Limits the number of in-flight requests to maintain order.

Additional Considerations

Monitoring and Logging: Enable monitoring and logging to keep track of retries and potential configuration mismatches or unexpected behavior in production.

Compression: Consider using compression (like gzip or snappy) to reduce the size of producer requests, especially if idempotence increases the number of retries and hence, the bandwidth consumption.

Transaction Support: For applications requiring transactional writes across multiple partitions, idempotence alone is not enough. You should also consider enabling transaction capabilities by configuring transactional.id.

Conclusion

Configuring your Kafka producer for idempotence is a critical step in building reliable distributed systems. It ensures data integrity and simplifies the application design by removing the need to handle duplicate messages. Properly configuring and monitoring your Kafka producers can thus provide significant benefits in maintaining robust data pipelines.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.