LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2022 min read

Messaging Dependencies (RabbitMQ & Kafka)

Learn how to add asynchronous messaging to a Spring Boot application with spring-boot-starter-amqp for RabbitMQ and spring-kafka for Kafka.

Introduction

Not every operation needs to happen synchronously inside an HTTP request. When one service needs to tell another "something happened" without waiting for an immediate response, message brokers let you decouple the two sides entirely. Spring offers first-class support for the two most popular brokers: RabbitMQ and Kafka.

What You Will Learn
  • Why asynchronous, broker-based messaging matters in microservice architectures.
  • How to send and receive messages with spring-boot-starter-amqp (RabbitMQ).
  • How to produce and consume events with spring-kafka.
  • When to reach for a traditional queue versus a log-based event stream.

Why Asynchronous Messaging?

Use case: order processing pipelines, email/notification fan-out, audit logging, or any workflow where the producer should not be blocked waiting on the consumer. A message broker sits between the two services, storing messages until a consumer is ready to process them, which improves resilience and lets services scale independently.

RabbitMQ with spring-boot-starter-amqp

spring-boot-starter-amqp adds Spring AMQP support for RabbitMQ, a traditional message queue broker. It gives you RabbitTemplate for publishing messages and the @RabbitListener annotation for consuming them.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

Declare a queue as a bean, then publish to it with RabbitTemplate.

RabbitConfig.java
@Configuration
public class RabbitConfig {
public static final String ORDER_QUEUE = "order.queue";
@Bean
public Queue orderQueue() {
return new Queue(ORDER_QUEUE, true); // durable
}
}
OrderProducer.java
@Service
public class OrderProducer {
private final RabbitTemplate rabbitTemplate;
public OrderProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void publishOrderCreated(String orderId) {
rabbitTemplate.convertAndSend(RabbitConfig.ORDER_QUEUE, orderId);
}
}
OrderConsumer.java
@Component
public class OrderConsumer {
@RabbitListener(queues = RabbitConfig.ORDER_QUEUE)
public void handleOrderCreated(String orderId) {
System.out.println("Processing order: " + orderId);
// e.g. update inventory, send confirmation email
}
}
Result

Click Run to see what this code prints.

Kafka with spring-kafka

spring-kafka integrates Spring with Apache Kafka, a distributed, log-based event streaming platform. Unlike RabbitMQ, Kafka retains events on disk for a configurable period, letting multiple independent consumers replay the same stream at their own pace.

pom.xml
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
application.properties
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=order-service
spring.kafka.consumer.auto-offset-reset=earliest
OrderEventProducer.java
@Service
public class OrderEventProducer {
private final KafkaTemplate<String, String> kafkaTemplate;
public OrderEventProducer(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void publishOrderCreated(String orderId) {
kafkaTemplate.send("order-events", orderId, "ORDER_CREATED");
}
}
OrderEventConsumer.java
@Component
public class OrderEventConsumer {
@KafkaListener(topics = "order-events", groupId = "order-service")
public void handleOrderEvent(ConsumerRecord<String, String> record) {
System.out.println("Key: " + record.key() + ", Event: " + record.value());
}
}
Result

Click Run to see what this code prints.

RabbitMQ vs Kafka

AspectRabbitMQ (Queue)Kafka (Log-Based Stream)
ModelMessage queue — a message is removed once consumedAppend-only log — events are retained and can be replayed
Best forTask distribution, RPC-style workflows, low-latency queuingHigh-throughput event streaming, event sourcing, analytics pipelines
Multiple consumersCompeting consumers split the workloadEach consumer group gets its own full copy of the stream
OrderingPer-queue, with routing complexity via exchangesGuaranteed per-partition
Choose whenYou need flexible routing and traditional task queuesYou need durable, replayable event history at scale

Common Mistakes

Avoid These Mistakes
  • Choosing Kafka for a simple task queue when RabbitMQ would be simpler to operate.
  • Forgetting to make RabbitMQ queues durable, losing messages on broker restart.
  • Not setting a stable Kafka consumer group-id, causing consumers to re-read or skip events unexpectedly.
  • Treating a message broker as a database — messages are meant to be transient work items or events, not long-term storage.

Best Practices

  • Make queues and exchanges durable in production RabbitMQ setups.
  • Use meaningful, versioned event payloads (e.g. JSON with a type field) rather than raw strings.
  • Handle consumer failures explicitly — configure retry and dead-letter queues.
  • Pick Kafka when you need replayability and multiple independent consumers of the same event stream; pick RabbitMQ for simpler task distribution.

Frequently Asked Questions

Yes, though it is uncommon. Some teams use RabbitMQ for internal task queues and Kafka for cross-service event streaming.

Yes, both require a running broker. Docker Compose is the easiest way to spin up RabbitMQ or Kafka locally for development.

RabbitMQ, generally — its concepts (queues, exchanges, routing keys) map more directly onto traditional messaging, while Kafka introduces additional concepts like partitions and consumer groups.

Summary

spring-boot-starter-amqp and spring-kafka bring asynchronous messaging into Spring Boot, letting services communicate through durable queues or replayable event streams instead of tight, synchronous HTTP calls.

Lesson 20 Completed
  • You understand why asynchronous messaging matters.
  • You built a RabbitMQ producer and consumer with spring-boot-starter-amqp.
  • You built a Kafka producer and consumer with spring-kafka.
  • You can explain when to choose a queue versus a log-based stream.
Next Lesson →

Spring Cloud Config & Discovery Dependencies