Enterprise Architecture · Enterprise · Topic 4 of 5
Multi-Tenant Kafka Configuration
One way to isolate tenants is by topic name (a tenant id in the topic) and, where isolation matters more, a consumer factory per tenant. A topicPattern subscription lets one listener cover all tenants' topics; the group discovers new matching topics through periodic metadata refreshes (metadata.max.age.ms, 5 minutes by default).
@Configuration
@Slf4j
public class TenantKafkaConfig {
// One listener subscribes to every topic matching the pattern
@KafkaListener(topicPattern = "tenant\\..*\\.order\\.created",
groupId = "multi-tenant-processor")
public void onTenantOrder(
ConsumerRecord<String, OrderEvent> record,
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic
) {
// Extract the tenant from the topic: tenant.{tenantId}.order.created
String tenantId = topic.split("\\.")[1];
tenantOrderService.process(tenantId, record.value());
}
}
// Publisher: routes to the tenant's topic
@Service
public class TenantOrderPublisher {
public void publish(String tenantId, OrderEvent event) {
String topic = String.format("tenant.%s.order.created", tenantId);
kafkaTemplate.send(topic, event.getOrderId(), event);
}
}
// Per-tenant consumer factory (for complete isolation)
@Bean
public Map<String, ConcurrentKafkaListenerContainerFactory<?, ?>> tenantFactories(
Map<String, TenantConfig> tenants
) {
return tenants.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> {
var config = entry.getValue();
Map<String, Object> props = new HashMap<>(commonProps);
props.put(BOOTSTRAP_SERVERS_CONFIG, config.getKafkaBrokers());
props.put(GROUP_ID_CONFIG, config.getTenantId() + "-processor");
var cf = new DefaultKafkaConsumerFactory<>(props);
var factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(cf);
return factory;
}
));
}Sources
- @KafkaListener annotation (Spring for Apache Kafka) (opens in a new tab)
- Message listener containers (Spring for Apache Kafka) (opens in a new tab)
- Consumer configs (Kafka 4.2 documentation) (opens in a new tab)
- KafkaConsumer Javadoc (4.2) (opens in a new tab)
Checked against Spring for Apache Kafka 4.1.1, Spring Boot 4.1.1 and Kafka 4.2 documentation on 11 October 2026. Draft: not yet reviewed by a Kafka specialist, and releases move on, so confirm against the current documentation before you act on it.