How to subscribe multiple topic using @KafkaListner annotation
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In Spring for Apache Kafka, a single listener method can subscribe to multiple topics by using the topics attribute on @KafkaListener. This is useful when the handling logic is the same or nearly the same across several streams. The main design question is not whether it is possible, but whether one listener method is the right structure for your topic layout and message semantics.
Subscribe to Several Topics With topics
The direct approach is to provide an array of topic names.
With that configuration, the same method receives records from both topics. Spring creates a listener container that subscribes to the provided topic names, and Kafka group management assigns partitions to consumer instances.
Read Which Topic the Message Came From
If you subscribe to multiple topics, you often need to branch based on the source topic. Spring lets you inject record metadata through headers or through ConsumerRecord.
Using a header:
That is often cleaner than parsing the topic from the raw consumer record unless you already need the full record metadata.
Use topicPattern for Dynamic Topic Sets
If the topic list changes often and follows a naming convention, a pattern can be a better choice than hard-coding names.
This subscribes to topics that match the pattern rather than a fixed list. It is useful for tenant-prefixed or environment-scoped topic families, but it should be used deliberately because it can pull in more topics than intended if the pattern is too broad.
Add Group and Concurrency Settings Carefully
In real applications, you usually specify a consumer group and sometimes concurrency as well.
The concurrency value creates multiple consumer threads in the listener container. That can increase throughput, but it only helps if the subscribed topics have enough partitions to keep those consumers busy.
When Separate Listeners Are Better
A single multi-topic listener is convenient when the message contract is the same across topics. If each topic needs very different deserialization, validation, retry handling, or business logic, separate listener methods are often clearer.
For example, combining JSON business events and plain text audit events in one method usually makes the code harder to reason about. Keeping them separate can simplify error handling and make configuration more explicit.
The rule of thumb is simple: share a listener when the behavior is genuinely shared, not just because the annotation allows it.
Property-Based Topic Names
Spring also allows externalized topic names, which is useful for environment-specific configuration.
This keeps deployment-specific topic names out of the compiled code while preserving the same multi-topic listener pattern.
Common Pitfalls
The first pitfall is putting unrelated topics into one listener method just because it is possible. That often creates messy conditional logic and mixed error-handling behavior.
Another issue is confusing topics with topicPattern. Fixed names belong in topics; pattern-based subscription belongs in topicPattern. They are mutually exclusive choices.
Developers also expect concurrency alone to increase throughput. If the topics do not have enough partitions, extra listener threads do not add useful parallelism.
Finally, the annotation in the title is misspelled. In code, the Spring annotation is @KafkaListener, not @KafkaListner.
Summary
- Use
@KafkaListener(topics = {"topic1", "topic2"})to subscribe one method to multiple topics. - Inject the received topic name when the handling logic depends on the source stream.
- Use
topicPatternonly when you intentionally want regex-based subscription. - Add
groupIdandconcurrencybased on your consumer-group design and partition count. - Split listeners when topics have meaningfully different payloads or operational requirements.
Related reading
- How to subscribe to a list of multiple kafka wildcard patterns using kafka-python?
- How to support multiple KeyBy in Flink
- How to suppress window using wall clock time instead of event time in Kafka streams?
- How to sync data for a particular user, when reading from kafka?
- How to test a ConsumerAwareRebalanceListener?
- How to test a Kafka Stream app without duplicating the topology? Use of TopologyTestDriver?
- How to test the connection to RabbitMQ Server?
- How to test whether log compaction is working or not in Kafka?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack 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.