Skip to content
Spring Boot sb messaging 5 min read

Messaging Intro

A synchronous REST call couples two services in time: the caller blocks until the callee responds, and if the callee is down the call fails. Asynchronous messaging breaks that coupling. The producer hands a message to a broker and moves on; the consumer processes it whenever it is ready. This is the backbone of resilient, scalable microservices — orders that survive a payment service restart, emails that send without slowing the checkout response, and spikes that drain through a queue instead of toppling a downstream service.

Why asynchronous messaging

In a synchronous architecture, OrderService calls InventoryService, PaymentService, and EmailService in sequence. Total latency is the sum of all four, and any one failure rolls back the user’s request. With messaging, OrderService publishes an OrderPlaced message and returns immediately; the other services consume it independently and at their own pace.

The benefits compound at scale:

  • Decoupling — the producer needs no knowledge of who consumes the message, or even whether anyone does yet.
  • Resilience — if a consumer is down, messages wait in the broker and are processed on recovery. No data is lost.
  • Load levelling — a sudden burst of messages buffers in the broker; consumers drain it at a sustainable rate instead of being overwhelmed.
  • Scalability — add more consumer instances to process a backlog faster, with no change to the producer.

What a message broker does

A message broker is middleware that receives messages from producers and routes them to consumers. It handles persistence, delivery guarantees, retries, and routing so your application code does not have to. The two brokers covered in this section sit at different ends of the spectrum:

AspectRabbitMQApache Kafka
ModelSmart broker, routes via exchangesDistributed commit log
Primary useTask queues, RPC, complex routingEvent streaming, high-throughput pipelines
Message retentionRemoved once acknowledgedRetained for a configurable period; re-readable
OrderingPer queuePer partition
ThroughputTens of thousands/secMillions/sec
Starterspring-boot-starter-amqpspring-kafka

Note: “Best” depends on the workload. RabbitMQ excels at routing individual tasks to workers; Kafka excels at durable, replayable event streams consumed by many independent readers.

Queues vs topics

These two terms describe delivery semantics, and the distinction underpins everything else.

  • A queue holds messages destined for a single logical consumer. Each message is delivered to exactly one consumer (across all instances), which is ideal for distributing work.
  • A topic broadcasts each message to every interested subscriber. Each subscriber receives its own copy.
QUEUE (point-to-point)            TOPIC (publish/subscribe)

producer --> [ q ] --> consumer   producer --> [ t ] --> consumer A
                                                     \-> consumer B
                                                     \-> consumer C

Point-to-point vs publish/subscribe

These are the two messaging patterns built on queues and topics.

Point-to-point routes each message to one consumer. If three worker instances share a queue, each message is processed by exactly one of them — the broker load-balances. Use it for commands and work distribution: “resize this image”, “charge this card”.

Publish/subscribe delivers each message to all subscribers. Use it for events that multiple parties care about: an OrderPlaced event might trigger inventory reservation, a confirmation email, and an analytics update — three independent consumers, each reacting to its own copy.

// Point-to-point: one consumer wins each message
@RabbitListener(queues = "image.resize")
public void resize(ResizeRequest req) { /* one worker handles it */ }

// Pub/sub: every subscriber gets its own copy (Kafka, distinct groups)
@KafkaListener(topics = "order.placed", groupId = "email-service")
public void onOrder(OrderPlaced event) { /* email reacts */ }

Tip: Kafka unifies both patterns through consumer groups. Instances in the same group split the partitions (point-to-point); separate groups each receive the full stream (pub/sub). RabbitMQ uses queues for point-to-point and fanout/topic exchanges for pub/sub.

When to use messaging vs REST

Messaging is powerful but not free — it adds a broker to operate, eventual consistency to reason about, and asynchronous flows that are harder to trace than a single HTTP call. Choose deliberately.

Use messaging when…Use REST/RestClient when…
The caller does not need an immediate resultThe caller needs the answer to continue
Work can be retried or processed laterThe operation is a simple, synchronous read
Multiple services react to one eventThere is exactly one well-known callee
You need load levelling under spikesLatency must be predictable and low
Producer and consumer scale independentlyThe interaction is a request/response query

Warning: Messaging introduces eventual consistency. After OrderService publishes OrderPlaced, the inventory may not be decremented for a few milliseconds — or seconds, under load. Design UIs and downstream logic to tolerate that lag rather than assuming instant propagation.

A common hybrid: accept the request over REST, publish a message internally, and return 202 Accepted. The client gets a fast acknowledgement while the heavy work happens asynchronously. See ResponseEntity for returning 202 with a status location.

Delivery guarantees

Brokers offer different guarantees, and you trade throughput for safety:

  • At-most-once — fire and forget; a message may be lost but never duplicated.
  • At-least-once — the default for most systems; a message is never lost but may be redelivered, so consumers must be idempotent.
  • Exactly-once — strongest and most expensive; Kafka supports it for stream processing with transactions.

Design consumers to be idempotent (safe to process the same message twice) and you can rely on the robust, widely-used at-least-once model.

In This Section

Last updated June 13, 2026
Was this helpful?