Skip to content
Kafka Is Fun

Production Patterns · Intermediate · Topic 5 of 5

Consumer with Message Headers

Kafka records can carry headers: small key-value metadata such as a trace ID or an event version. Spring can inject the record's topic, partition and offset, and your own headers, into listener parameters.

HeaderAwareConsumer.javajava
@Service
public class HeaderAwareConsumer {

    // Inject specific headers via @Header
    @KafkaListener(topics = "orders.order.created")
    public void onOrder(
        OrderEvent event,
        @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
        @Header(KafkaHeaders.RECEIVED_PARTITION) int partition,
        @Header(KafkaHeaders.OFFSET) long offset,
        @Header(name = "X-Trace-Id", required = false) String traceId,
        @Header(name = "X-Event-Version", required = false) String eventVersion
    ) {
        MDC.put("traceId", traceId != null ? traceId : "unknown");
        log.info("Processing order from {}-{} @ offset {}", topic, partition, offset);
        // process...
    }
}

// Producer: add headers
@Service
public class TracingOrderProducer {

    public void publish(Order order) {
        var record = new ProducerRecord<>("orders.order.created",
            null, System.currentTimeMillis(), order.getId(),
            new OrderCreatedEvent(order));

        record.headers()
            .add(new RecordHeader("X-Trace-Id", TraceContext.current().toBytes()))
            .add(new RecordHeader("X-Event-Version", "2".getBytes()))
            .add(new RecordHeader("X-Source-Service", "order-service".getBytes()));

        kafkaTemplate.send(record);
    }
}

Sources

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.