---
title: "Kafka Integration"
description: "Learn how to trace Kafka queue operations with Sentry."
url: https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka/
---

# Kafka Integration | Sentry for Spring Boot

Sentry's Kafka integration lets you trace both production and consumption. In Spring Boot, this happens automatically. If you're using raw `kafka-clients`, you'll need to instrument producers and consumers with `sentry-kafka`.

Once configured, queue spans will appear in Sentry's [Queues dashboard](https://sentry.io/orgredirect/organizations/:orgslug/insights/backend/queues/).

Kafka queue tracing is available in Sentry Java SDK version `8.41.0` and later.

If you're using Spring Kafka (`KafkaTemplate` / `@KafkaListener`), Sentry instruments your producers and consumers automatically. If you're using `kafka-clients` directly, see the [Java Kafka docs](https://docs.sentry.io/platforms/java/integrations/kafka.md) for manual instrumentation with `sentry-kafka`.

### [Install](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#install)

Add `sentry-kafka` alongside your existing Spring Kafka dependency:

```groovy
implementation 'io.sentry:sentry-kafka:8.41.0'
implementation 'org.springframework.kafka:spring-kafka'
```

### [Configure](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#configure)

Enable queue tracing in your application properties:

```properties
sentry.dsn=___DSN___

sentry.enable-queue-tracing=true

sentry.traces-sample-rate=1.0
```

Now every `KafkaTemplate.send(...)` call produces a `queue.publish` span if there's a transaction running, and record-based `@KafkaListener` methods produce `queue.process` transactions. Sentry injects propagation headers (`sentry-trace`, `baggage`) into outgoing records and continues the trace on the consumer side.

### [Producer](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#producer)

```java
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    private final KafkaTemplate<String, String> kafkaTemplate;

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

    @GetMapping("/order")
    public String placeOrder() {
        // Sentry automatically records a queue.publish span for this send.
        kafkaTemplate.send("orders", "order-payload");
        return "ok";
    }
}
```

### [Consumer](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#consumer)

```java
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

@Component
public class OrderConsumer {

    @KafkaListener(topics = "orders", groupId = "order-group")
    public void onOrder(ConsumerRecord<String, String> record) {
        // Sentry automatically records a queue.process transaction for this method.
        processOrder(record.value());
    }
}
```

### [Enable Retry Count](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#enable-retry-count)

Sentry sets `messaging.message.retry.count` from Spring Kafka's `kafka_deliveryAttempt` header. Spring Kafka only adds this header when delivery attempt headers are enabled and the listener uses an error handler or after-rollback processor that supports delivery attempts.

The following example uses Spring Kafka's `DefaultErrorHandler`. If your app already uses retry handling that supports delivery attempts, keep your existing handler and enable the header on the listener container:

```java
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.config.ContainerCustomizer;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
import org.springframework.kafka.listener.DefaultErrorHandler;
import org.springframework.util.backoff.FixedBackOff;

@Bean
DefaultErrorHandler kafkaErrorHandler() {
    return new DefaultErrorHandler(new FixedBackOff(0L, 1L));
}

@Bean
ContainerCustomizer<Object, Object, ConcurrentMessageListenerContainer<Object, Object>>
    kafkaContainerCustomizer() {
    return container -> container.getContainerProperties().setDeliveryAttemptHeader(true);
}
```

Without that header, Sentry does not set `messaging.message.retry.count`.

## [Span Data](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#span-data)

| Attribute                           | Type   | Description                                                                                          |
| ----------------------------------- | ------ | ---------------------------------------------------------------------------------------------------- |
| `messaging.system`                  | string | Always `"kafka"`                                                                                     |
| `messaging.destination.name`        | string | Kafka topic name                                                                                     |
| `messaging.message.id`              | string | Value of the `messaging.message.id` record header, if present                                        |
| `messaging.message.body.size`       | int    | Serialized value size in bytes                                                                       |
| `messaging.message.retry.count`     | int    | Number of previous delivery attempts (from Kafka's `kafka_deliveryAttempt` header), if present       |
| `messaging.message.receive.latency` | int    | Time in milliseconds between the producer sending the record and the consumer starting to process it |

## [Limitations](https://docs.sentry.io/platforms/java/guides/spring-boot/integrations/kafka.md#limitations)

* **Async listeners not supported.** `@KafkaListener` methods that return a `CompletableFuture` or `Mono`/`Flux` are not instrumented correctly; use synchronous listeners.
* **Batch listeners not supported.** `@KafkaListener` methods that consume batches, such as `ConsumerRecords<?, ?>` or `List<ConsumerRecord<...>>`, are not instrumented yet.
* **Spring Boot auto-instrumentation is disabled when using Sentry OpenTelemetry integrations.**
