skip to content

Publisher Confirms & Returns

Publisher confirms tell you asynchronously whether the broker accepted a message, and the mandatory flag with a returns callback catches messages that route nowhere. Interviewers ask how you know a publish actually succeeded — and 'no exception' is not the answer.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What are RabbitMQ publisher confirms in Spring AMQP, and what problem do they solve?

level: juniorimportance: must knowfreq 62%

answer

  1. fire-and-forget -> async ack
  2. setPublisherConfirmType(CORRELATED)
  3. ack = broker accepted, nack = rare failure
  4. confirm != consumer processed
  5. unroutable is still acked

basics

~20 s

By default, sending a message via RabbitTemplate doesn't tell you if the broker actually received it. Publisher confirms make the broker send back an async ack (or nack) per message, so the producer knows the send succeeded.

solid answer

~40 s

Plain AMQP publishing is fire-and-forget: RabbitTemplate.convertAndSend() returns as soon as the message leaves the client, giving no proof the broker stored it. Publisher confirms are a RabbitMQ extension where the broker asynchronously returns an ack once it has accepted the message (persisted it for durable messages, or routed it to queues). In Spring AMQP you enable it on the CachingConnectionFactory with setPublisherConfirmType(ConfirmType.CORRELATED), then register a RabbitTemplate.ConfirmCallback (or use the CorrelationData future). You get a callback with (correlationData, ack, cause): ack=true means the broker accepted it, ack=false (a nack) means it couldn't. This closes the reliability gap between 'my send call returned' and 'the broker has the message', which matters for anything that must not silently lose data.

go deeper

for a junior

Know that plain sends are fire-and-forget and confirms give an async ack/nack from the broker.

for a middle

Enable via setPublisherConfirmType(CORRELATED) and register a ConfirmCallback; understand ack vs nack.

for a senior

Distinguish confirm (broker accepted) from routing (mandatory/returns) and from consumer ack; know callbacks run on amqp threads.

for a principal

Reason about end-to-end guarantees, timeout handling, and combining confirms with persistence and returns for at-least-once producing.

## The problem With raw AMQP, `basic.publish` has no response. When you call `rabbitTemplate.convertAndSend(exchange, routingKey, payload)`, the method returns as soon as the bytes are handed to the client library's channel. If the broker crashes, is out of disk, or the connection drops mid-flight, the producer never finds out — the message is silently lost. This is 'fire and forget'. ## Publisher confirms **Publisher confirms** (a.k.a. 'confirms' or 'publisher acknowledgements') are a RabbitMQ protocol extension. When enabled on a channel, the broker sends back an **asynchronous acknowledgement** for each published message: - **ack** — the broker has taken responsibility for the message. For a persistent message routed to a durable queue, this means it was written to disk; for a transient message it means it was routed to (accepted by) all the matching queues. - **nack** — the broker could NOT take responsibility (e.g. an internal error, out of resources). Nacks are rare. Confirms are **asynchronous and out-of-band**: publishing stays fast; the acks stream back separately, possibly batched, and not necessarily in send order. ## Enabling it in Spring AMQP Confirms are configured on the `CachingConnectionFactory`: ```java CachingConnectionFactory cf = new CachingConnectionFactory("localhost"); cf.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED); ``` Three modes: - `ConfirmType.NONE` (default) — confirms off. - `ConfirmType.SIMPLE` — enables confirms and lets you call `channel.waitForConfirms()` via `rabbitTemplate.invoke(...)` for a synchronous, blocking wait. - `ConfirmType.CORRELATED` — enables confirms and delivers the result to a callback, carrying a `CorrelationData` you attached at send time so you can match the ack to the specific message. Then on the `RabbitTemplate` you register a `RabbitTemplate.ConfirmCallback`: ```java template.setConfirmCallback((correlationData, ack, cause) -> { if (ack) { /* broker accepted */ } else { /* nack: cause has the reason */ } }); ``` ## What a confirm does and does NOT mean - It **does** mean the broker received/stored/routed the message. - It does **not** mean any consumer processed it — that's consumer acknowledgements, a separate concept. - An ack does **not** mean the message reached a queue if there was no matching queue: an unroutable message is still **acked** (the broker accepted it, then dropped it). Detecting 'accepted but not routed to any queue' needs the **mandatory flag + returns**, which is a separate mechanism. ## Gotchas - Requires the `CachingConnectionFactory` (channels must be cached/tracked). - Callbacks run on a **listener/amqp thread**, not your publishing thread — keep them fast and thread-safe. - There is no automatic timeout: if a confirm never arrives (connection lost), your callback simply never fires unless you add your own timeout handling. ## When to use Use confirms whenever losing a produced message is unacceptable (payments, orders, event sourcing). Combine with **persistent messages + durable queues + mandatory returns** for end-to-end producer reliability.

  • Does an ack guarantee a consumer processed the message?
    No. A confirm only means the broker accepted/stored/routed the message. Whether a consumer received and processed it is a separate concern handled by consumer acknowledgements.
  • What's the difference between ConfirmType.SIMPLE and ConfirmType.CORRELATED?
    SIMPLE enables a synchronous blocking wait via channel.waitForConfirms() (through template.invoke). CORRELATED enables async callbacks that carry the CorrelationData you attached, so you can match each ack to its message.

saying these in an interview costs you the question

  • Thinking a publisher confirm means a consumer received the message
  • Believing convertAndSend already blocks until the broker confirms
  • Assuming an unroutable message produces a nack (it's actually acked)
  • Not knowing confirms require the CachingConnectionFactory to be configured

context

open as a page

How does the mandatory flag together with ReturnsCallback handle unroutable messages, and why can't publisher confirms alone detect them?

level: middleimportance: must knowfreq 55%

basics

~20 s

Set the mandatory flag on RabbitTemplate. If a published message can't be routed to any queue, the broker returns it and your ReturnsCallback fires. Confirms can't catch this because the broker still acks unroutable messages.

open as a page

Show how to configure a RabbitTemplate for correlated publisher confirms and returns, and explain what each piece does.

level: middleimportance: should knowfreq 38%

basics

~10 s

Set ConfirmType.CORRELATED and publisherReturns(true) on the CachingConnectionFactory, then on the RabbitTemplate call setMandatory(true), setConfirmCallback(...) for acks/nacks, and setReturnsCallback(...) for unroutable messages.

open as a page

How do you correlate an asynchronous ack/nack back to the specific message that was sent, using CorrelationData?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Attach a CorrelationData (with a unique id) as an extra argument when you send. Because confirms are async and unordered, the ConfirmCallback receives that same CorrelationData, letting you look up which message the ack/nack belongs to. You can also await its CompletableFuture.

open as a page

Design a reliable producer path: what do publisher confirms guarantee, what edge cases remain, and how would you achieve at-least-once publishing?

level: principalimportance: should knowfreq 30%

basics

~20 s

Confirms tell you the broker accepted a message, mandatory+returns catch unroutable ones. But confirms are async with no timeout and can be lost, and retries create duplicates. For at-least-once, persist an outbox row, publish, mark confirmed on ack, sweep/retry unconfirmed, and make consumers idempotent.

open as a page