Kafka Template
Spring Boot
Multiple Templates
Java Development
Application Design

Can we use multiple kafka template in spring boot?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Yes. Spring Boot can use multiple KafkaTemplate beans in the same application, and that is the normal approach when different topics, clusters, serializers, or reliability settings need separate producer configurations. The key is to define distinct ProducerFactory and KafkaTemplate beans and inject them with qualifiers.

When Multiple Templates Make Sense

You do not need multiple templates just because you publish to multiple topics. One KafkaTemplate can send to many topics if the producer settings are the same.

Multiple templates are useful when any of these differ:

  • bootstrap servers
  • key or value serializer
  • transactional settings
  • security configuration
  • producer tuning such as acks or compression

For example, a service might send plain text audit events to one cluster and Avro-encoded business events to another.

Define Separate Beans

The cleanest setup is to create one producer factory per configuration and one template per factory.

java
1import java.util.HashMap;
2import java.util.Map;
3import org.apache.kafka.clients.producer.ProducerConfig;
4import org.apache.kafka.common.serialization.StringSerializer;
5import org.springframework.context.annotation.Bean;
6import org.springframework.context.annotation.Configuration;
7import org.springframework.beans.factory.annotation.Qualifier;
8import org.springframework.kafka.core.DefaultKafkaProducerFactory;
9import org.springframework.kafka.core.KafkaTemplate;
10import org.springframework.kafka.core.ProducerFactory;
11import org.springframework.kafka.support.serializer.JsonSerializer;
12
13@Configuration
14public class KafkaProducerConfig {
15
16    @Bean
17    public ProducerFactory<String, String> textProducerFactory() {
18        Map<String, Object> props = new HashMap<>();
19        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
20        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
21        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
22        return new DefaultKafkaProducerFactory<>(props);
23    }
24
25    @Bean
26    public KafkaTemplate<String, String> textKafkaTemplate() {
27        return new KafkaTemplate<>(textProducerFactory());
28    }
29
30    @Bean
31    public ProducerFactory<String, OrderEvent> orderProducerFactory() {
32        Map<String, Object> props = new HashMap<>();
33        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9093");
34        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
35        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
36        return new DefaultKafkaProducerFactory<>(props);
37    }
38
39    @Bean
40    public KafkaTemplate<String, OrderEvent> orderKafkaTemplate() {
41        return new KafkaTemplate<>(orderProducerFactory());
42    }
43}

Now each template has its own producer settings and value type.

Inject the Right Template

Use @Qualifier so Spring knows which template you want.

java
1import org.springframework.beans.factory.annotation.Qualifier;
2import org.springframework.kafka.core.KafkaTemplate;
3import org.springframework.stereotype.Service;
4
5@Service
6public class EventPublisher {
7    private final KafkaTemplate<String, String> textKafkaTemplate;
8    private final KafkaTemplate<String, OrderEvent> orderKafkaTemplate;
9
10    public EventPublisher(
11            @Qualifier("textKafkaTemplate") KafkaTemplate<String, String> textKafkaTemplate,
12            @Qualifier("orderKafkaTemplate") KafkaTemplate<String, OrderEvent> orderKafkaTemplate) {
13        this.textKafkaTemplate = textKafkaTemplate;
14        this.orderKafkaTemplate = orderKafkaTemplate;
15    }
16
17    public void publishAudit(String message) {
18        textKafkaTemplate.send("audit-log", message);
19    }
20
21    public void publishOrder(OrderEvent event) {
22        orderKafkaTemplate.send("orders", event.orderId(), event);
23    }
24}
25
26record OrderEvent(String orderId, double total) {}

Without qualifiers, Spring may fail with a “multiple beans found” error.

Keep the Configuration Maintainable

For production systems, hard-coded server addresses are not ideal. A better pattern is to bind settings from application.yml into separate property classes. That keeps credentials and cluster endpoints out of the Java config and makes environment-specific deployment easier.

Even if you start with manual bean definitions, keep the separation clear: one logical producer configuration per use case.

It is also worth testing each template in isolation. A message that works through the text producer may still fail through the JSON producer because of serializer settings, headers, or topic-level expectations. Separate integration tests make those failures easier to localize.

Common Pitfalls

The biggest mistake is creating multiple templates when only the topic changes. That adds bean noise without solving a real problem.

Another mistake is reusing the wrong serializer. A template configured with StringSerializer for values cannot safely send JSON objects just because the generic type says it can.

Teams also forget qualifiers. Once two beans of the same type exist, constructor injection must identify the intended one explicitly.

Summary

  • Spring Boot can use multiple KafkaTemplate beans in one application.
  • Create separate ProducerFactory and KafkaTemplate beans for each producer configuration.
  • Use @Qualifier when injecting templates so Spring can resolve the correct bean.
  • Multiple templates are useful for different clusters, serializers, or producer settings, not just different topics.
  • Keep configuration externalized once the setup grows beyond a simple local example.

Course illustration
Course illustration

All Rights Reserved.