Home/Learn/RabbitMQ/Publisher Confirms

Publisher Confirms

Intermediate
Reliability

Publisher confirms are an async acknowledgement from the broker that a message was routed and written; essential to know a message is not lost between producer and broker.

Overview

When a producer publishes a message to RabbitMQ using the standard basicPublish, the call returns immediately with no feedback — the producer has no idea whether the broker received and persisted the message. If the broker is busy, the network drops, or the broker crashes, the message is silently lost. Publisher Confirms (also called broker confirms) solve this: the channel is put in confirm mode, and the broker sends an ack (or nack) for every message it has received and durably written. Combines with persistent messages and durable queues to form a complete message-safety story. Spring AMQP's CorrelationData and PublisherCallbackChannelConnectionFactory make publisher confirms straightforward to use in production.

How Publisher Confirms Work

The producer puts the channel in confirm mode (channel.confirmSelect()). From this point every message sent on the channel is assigned a monotonically increasing delivery tag (sequence number). The broker sends basicAck for durably persisted messages, or basicNack for messages it could not process (e.g., disk full, mandatory message not routed). The producer can wait synchronously (waitForConfirms) or register an async listener (addConfirmListener) that fires on ack/nack — async is preferred for throughput.

Java — Publisher Confirms (AMQP Client)
Channel channel = connection.createChannel();

// Put channel in confirm mode — every publish gets a sequence number
channel.confirmSelect();

// Async confirm listener — fires on broker ack or nack
channel.addConfirmListener(
    (deliveryTag, multiple) -> {
        // ACK: broker persisted the message
        log.info("Confirmed delivery tag {}", deliveryTag);
    },
    (deliveryTag, multiple) -> {
        // NACK: broker could NOT persist — resend or alert
        log.error("Broker nacked delivery tag {} — message lost!", deliveryTag);
        retryPublish(deliveryTag);
    }
);

// Publish a persistent message
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
    .deliveryMode(2)   // persistent
    .build();

channel.basicPublish("orders", "order.created", props, messageBody);

// Synchronous wait — blocks until all pending confirms arrive (lower throughput)
boolean allConfirmed = channel.waitForConfirms(5000); // 5s timeout
if (!allConfirmed) {
    throw new RuntimeException("Some messages not confirmed by broker");
}

Spring AMQP — Publisher Confirms with CorrelationData

Spring AMQP exposes publisher confirms via RabbitTemplate with a ConfirmCallback and a ReturnCallback. Set publisherConfirmType=CORRELATED in the connection factory. Pass a CorrelationData object to convertAndSend to correlate acks/nacks back to the original send operation.

YAML + Java — Spring AMQP Publisher Confirms
# application.yml
spring:
  rabbitmq:
    publisher-confirm-type: correlated   # enables publisher confirms
    publisher-returns: true              # enables mandatory routing returns

@Configuration
public class RabbitConfig {
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory cf) {
        RabbitTemplate template = new RabbitTemplate(cf);
        template.setMandatory(true);  // returns unroutable messages

        // Called when broker ACKs or NACKs the message
        template.setConfirmCallback((correlationData, ack, cause) -> {
            String messageId = correlationData != null ? correlationData.getId() : "?";
            if (ack) {
                log.info("Message {} confirmed by broker", messageId);
            } else {
                log.error("Message {} NOT confirmed: {}", messageId, cause);
                // Re-queue for retry / alert
            }
        });

        // Called when a message is returned (not routed to any queue)
        template.setReturnsCallback(returned -> {
            log.warn("Message returned — not routed: {} → {} {}",
                returned.getRoutingKey(), returned.getReplyCode(), returned.getReplyText());
        });

        return template;
    }
}

// Publisher — pass CorrelationData for traceability
@Service
@RequiredArgsConstructor
public class OrderPublisher {
    private final RabbitTemplate rabbitTemplate;

    public void publish(Order order) {
        CorrelationData cd = new CorrelationData(order.getId().toString());
        rabbitTemplate.convertAndSend("orders", "order.created", order, cd);
    }
}

Transactional Publish vs Publisher Confirms

RabbitMQ also supports channel-level transactions (channel.txSelect, txCommit, txRollback) for synchronous, grouped commit. However, transactions are roughly 250× slower than publisher confirms (they require a full round-trip for each txCommit). Always prefer publisher confirms for production throughput. Use transactions only when you must atomically publish to multiple exchanges in a single rollback-able operation.

Java — Confirms vs Transactions
// AVOID: channel transactions — very slow
channel.txSelect();
try {
    channel.basicPublish(...);
    channel.basicPublish(...);
    channel.txCommit();  // synchronous, blocks, ~250x slower than confirms
} catch (Exception e) {
    channel.txRollback();
}

// PREFER: publisher confirms — async, fast, same safety guarantee
channel.confirmSelect();
channel.addConfirmListener(ackCallback, nackCallback);
channel.basicPublish(...);
channel.basicPublish(...);
// No blocking — confirm callbacks fire asynchronously

Key Points to Remember

  • 1Without publisher confirms, basicPublish is fire-and-forget — messages can be silently lost on broker failure or network drop.
  • 2Confirm mode (channel.confirmSelect) assigns a delivery tag to each message; broker sends ack or nack asynchronously.
  • 3Async confirm listeners (addConfirmListener) are preferred over waitForConfirms() for production throughput.
  • 4Spring AMQP: set publisher-confirm-type=CORRELATED and ConfirmCallback + ReturnsCallback on RabbitTemplate.
  • 5Publisher confirms + durable queues + persistent messages = complete end-to-end message durability guarantee.
  • 6Channel transactions are ~250× slower than confirms — use confirms for throughput-sensitive production code.

Interview Questions

Sign in to ask Aria
1

What problem do publisher confirms solve in RabbitMQ?

EasyAmazon
2

What is the difference between a publisher confirm ACK and a consumer ACK in RabbitMQ?

MediumUber
3

How do you implement publisher confirms in Spring AMQP?

MediumFlipkart
4

Why are channel transactions slower than publisher confirms?

MediumNetflix
5

How would you implement a reliable message outbox for RabbitMQ similar to Kafka's EOS?

HardLinkedIn

Ask Aria about Publisher Confirms

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…