skip to content

KafkaTemplate & Producers

KafkaTemplate sends records asynchronously, returning a future, with a producer factory, serializers and key-based partitioning underneath. Interviewers ask how the key determines the partition and why that matters for ordering.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

6

What is KafkaTemplate and how do you use it to send a message to a Kafka topic in Spring?

level: juniorimportance: must knowfreq 78%

answer

  1. thin wrapper over native KafkaProducer
  2. needs a ProducerFactory
  3. send(topic, key, value) -> CompletableFuture<SendResult>
  4. Boot auto-configures from spring.kafka.*
  5. thread-safe singleton

basics

~10 s

KafkaTemplate is Spring's helper for producing messages. You inject it and call template.send("topic", key, value). Spring Boot auto-configures it from application.properties, so you just autowire and send.

solid answer

~30 s

KafkaTemplate<K,V> is Spring for Apache Kafka's central producer abstraction — a thin, thread-safe wrapper over the native Kafka Producer. Spring Boot auto-configures a bean when spring-kafka is on the classpath and spring.kafka.* properties are set, wiring in a ProducerFactory. You inject it and call send(topic, value), send(topic, key, value), or send(ProducerRecord). It serializes the key/value with the configured serializers, hands the record to the underlying producer's send, and returns a CompletableFuture<SendResult<K,V>> for the async result. You can also set a defaultTopic. It centralizes producer config (bootstrap servers, serializers, acks) so business code just calls send.

code

java · 21 lines
java
@Service
public class OrderProducer {
    private final KafkaTemplate<String, String> kafkaTemplate;

    public OrderProducer(KafkaTemplate<String, String> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    public void publish(String orderId, String payload) {
        // key = orderId ensures per-order ordering on one partition
        kafkaTemplate.send("orders", orderId, payload);
    }
}

// application.yml
// spring:
//   kafka:
//     bootstrap-servers: localhost:9092
//     producer:
//       key-serializer: org.apache.kafka.common.serialization.StringSerializer
//       value-serializer: org.apache.kafka.common.serialization.StringSerializer

go deeper

for a junior

Know it's the Spring class for sending, that you inject it and call send(topic, key, value), and that Boot auto-configures it.

for a middle

Explain the ProducerFactory relationship, the send overloads, and that it returns a future.

for a senior

Discuss thread-safety, serializer wiring, defaultTopic, and that failures surface via the future not an exception.

for a principal

Frame it as a thin managed wrapper; reason about shared-producer semantics, config centralization, and where transactions/idempotence plug in via the factory.

**KafkaTemplate** (`org.springframework.kafka.core.KafkaTemplate<K,V>`) is the producer-side entry point of the *Spring for Apache Kafka* project. Kafka's own client library gives you a low-level `org.apache.kafka.clients.producer.KafkaProducer` that you must construct, configure, and close yourself. KafkaTemplate wraps that producer and gives it a Spring flavor: it's a managed bean, it's thread-safe, and it removes boilerplate. **How it gets created.** KafkaTemplate needs a `ProducerFactory<K,V>`, which knows how to create the underlying Kafka `Producer` (bootstrap servers, key/value serializers, acks, etc.). With Spring Boot, adding the `spring-kafka` dependency and setting `spring.kafka.bootstrap-servers`, `spring.kafka.producer.key-serializer`, and `spring.kafka.producer.value-serializer` in `application.yml` triggers auto-configuration that creates both a `DefaultKafkaProducerFactory` and a `KafkaTemplate` bean for you. Without Boot you declare these `@Bean`s yourself. **Sending.** The core overloads are: - `send(String topic, V data)` — value only; key is null. - `send(String topic, K key, V data)` — key + value (key drives partitioning). - `send(String topic, Integer partition, K key, V data)` — explicit partition. - `send(ProducerRecord<K,V> record)` — full control including headers and timestamp. - `sendDefault(...)` — uses the `defaultTopic` configured on the template. Every `send` is **asynchronous**: it returns a `CompletableFuture<SendResult<K,V>>` that completes when the broker acknowledges (or fails). The record is placed into the producer's in-memory batch buffer and flushed by a background I/O thread. **Terms defined.** - *Serializer*: converts your K/V objects to `byte[]` for the wire (e.g. `StringSerializer`, `JsonSerializer`). - *ProducerRecord*: the unit sent to Kafka — topic, optional partition, optional key, value, headers, timestamp. - *SendResult*: what you get back on success — the original `ProducerRecord` plus `RecordMetadata` (topic, partition, offset, timestamp) assigned by the broker. **When to use.** Any time application code needs to publish to Kafka. It's the standard, and you almost never touch the raw `KafkaProducer`. **Gotchas.** (1) send() does *not* throw on delivery failure synchronously — you must handle the returned future or you'll silently lose errors. (2) The template is thread-safe and meant to be a singleton — don't create one per request. (3) It only *produces*; consuming is a separate concern (`@KafkaListener` / `KafkaTemplate` is not for reading).

  • Does send() block until the broker acknowledges the message?
    No. send() is asynchronous — it buffers the record and returns a CompletableFuture<SendResult> immediately. It completes later on the producer I/O thread. To block you'd call .get() on the future (with the risk of blocking the caller).
  • Where does KafkaTemplate get its configuration from?
    From its ProducerFactory (usually DefaultKafkaProducerFactory), which holds the producer config map — bootstrap servers, serializers, acks, etc. Spring Boot builds it from spring.kafka.producer.* properties.

saying these in an interview costs you the question

  • Thinking send() blocks until acknowledged / is synchronous by default
  • Creating a new KafkaTemplate per request instead of reusing the singleton bean
  • Believing KafkaTemplate is also used for consuming messages
  • Assuming a delivery error is thrown from send() rather than surfaced via the returned future

context

open as a page

KafkaTemplate.send() returns a CompletableFuture<SendResult> — what does that mean for correctness, and how do you handle success and failure?

level: middleimportance: must knowfreq 72%

basics

~20 s

send() is asynchronous — it returns a future that completes when Kafka acknowledges the write. You attach whenComplete/thenAccept callbacks to handle the SendResult on success or the exception on failure, instead of assuming send succeeded.

open as a page

How do you send Java objects (POJOs) as JSON with KafkaTemplate, and what should you know about Spring's JsonSerializer?

level: middleimportance: should knowfreq 58%

basics

~10 s

Configure the value-serializer as Spring's JsonSerializer. It uses Jackson to turn your POJO into JSON bytes. Then send(topic, key, pojo) works directly. The consumer side uses JsonDeserializer to reconstruct the object.

open as a page

How does the message key passed to KafkaTemplate.send() affect partitioning, and when would you write a custom Partitioner?

level: seniorimportance: should knowfreq 63%

basics

~20 s

The key decides the partition: Kafka hashes the key and maps it to a partition, so all records with the same key go to the same partition and stay ordered. With a null key, records are spread across partitions. A custom Partitioner overrides this mapping.

open as a page

What is the role of ProducerFactory / DefaultKafkaProducerFactory, and how does it manage the underlying Kafka producer(s)?

level: seniorimportance: should knowfreq 55%

basics

~10 s

ProducerFactory creates the underlying Kafka Producer objects for KafkaTemplate, holding the config and serializers. DefaultKafkaProducerFactory is the standard implementation; by default it creates one shared, thread-safe producer that all sends reuse.

open as a page

As a principal engineer, how do you configure KafkaTemplate/ProducerFactory for durable, exactly-once-style delivery, and what are the trade-offs?

level: principalimportance: should knowfreq 40%

basics

~20 s

Set acks=all and enable.idempotence=true on the ProducerFactory for durable, non-duplicating writes. For atomic multi-message sends, add a transactionIdPrefix so the template runs Kafka transactions. The trade-off is lower throughput and higher latency for stronger guarantees.

open as a page