100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Messaging

Publisher Confirms

Learn how RabbitMQ's publisher confirm mechanism lets a producer know for certain that a message was safely received and persisted by the broker, closing the gap that durability alone leaves open.

ReliabilityIntermediate8 min readJul 10, 2026
Analogies

Why Publisher Confirms Exist

By default, basic.publish is fire-and-forget: the client library returns as soon as the frame is written to the TCP socket, with no guarantee the broker actually received or stored it. If the connection drops mid-frame, or the broker rejects the message because a queue is missing or full, the publisher has no way to know unless it opts into publisher confirms. Enabling confirms on a channel makes RabbitMQ send back a basic.ack (or basic.nack if something went wrong internally, such as an internal broker error) for each published message once it has been handled according to the queue's guarantees, giving the publisher a definitive signal to act on.

🏏

Cricket analogy: It is like a batter running a single without looking at the fielder's throw — basic.publish sends the ball but doesn't wait to see if the run-out attempt succeeds; publisher confirms are the umpire's raised finger telling you definitively whether it counted.

Using Confirms in Practice

You enable confirms once per channel with confirm_select (or confirmSelect in Java), after which every subsequent publish is tracked by a monotonically increasing delivery tag. In synchronous mode you can call wait_for_confirms after each publish, but this serializes publishing and kills throughput; the recommended production pattern is asynchronous confirms, where you register callbacks for ack and nack events and track outstanding delivery tags in a map, removing them as acks arrive and re-publishing or alerting on nacks. Batching publishes and confirming in bulk (RabbitMQ can ack a range of delivery tags with the multiple flag) is what makes confirms viable at high throughput.

🏏

Cricket analogy: It is like a team not waiting for the third umpire's decision on every single delivery before bowling the next ball — they keep play moving and only stop to react when a specific review comes back, exactly like tracking outstanding delivery tags asynchronously.

python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.confirm_delivery()  # enables publisher confirms on this channel

try:
    channel.basic_publish(
        exchange='orders',
        routing_key='orders.new',
        body='{"order_id": 991}',
        properties=pika.BasicProperties(delivery_mode=2),
        mandatory=True,
    )
    print('Broker confirmed persistence of the message')
except pika.exceptions.UnroutableError:
    print('Message was returned unroutable, never reached a queue')
except pika.exceptions.NackError:
    print('Broker nacked the message, publish failed internally')

Publisher confirms tell you the broker accepted and stored the message according to the queue's durability contract — they do NOT tell you a consumer ever processed it. For end-to-end delivery guarantees you still need consumer acknowledgments on the receiving side; confirms and consumer acks solve two different halves of the reliable-messaging problem.

Confirms with Mandatory Publishing

Confirms only tell you the broker accepted the message onto some queue via the exchange's bindings — they say nothing about whether that binding actually existed. Combine confirms with the mandatory flag to catch unroutable messages explicitly: if no queue is bound to the exchange for the given routing key, RabbitMQ returns the message to the publisher via a basic.return callback instead of silently discarding it, and this happens before the ack/nack for that message. Without mandatory, a misconfigured routing key silently drops messages even though the broker will happily ack the publish, because from the exchange's point of view it successfully processed the (unroutable) message.

🏏

Cricket analogy: It is like a fielder confirming they caught the ball cleanly but the umpire never checking whether it carried inside the boundary rope — mandatory publishing is the extra check that catches a catch taken outside the actual field of play.

basic.return callbacks for unroutable mandatory messages arrive asynchronously and can arrive interleaved with confirms for other messages, so don't assume the very next event after a publish is that message's return. Track messages by a correlation ID in the message properties, not by publish order, when handling mandatory returns at scale.

  • basic.publish is fire-and-forget by default; publisher confirms make broker acceptance explicit via ack/nack.
  • Enable confirms once per channel with confirm_select, then track delivery tags per publish.
  • Synchronous wait_for_confirms per message kills throughput; use asynchronous ack/nack callbacks in production.
  • Confirms guarantee broker-side storage per the queue's durability contract, not that a consumer processed the message.
  • The multiple flag lets RabbitMQ ack/nack a range of delivery tags at once for efficient batching.
  • Combine confirms with the mandatory flag and basic.return handling to catch unroutable messages instead of silent drops.
  • Track mandatory returns by correlation ID, since basic.return events arrive asynchronously and can interleave.

Practice what you learned

Was this page helpful?

Topics covered

#Messaging#RabbitMQStudyNotes#Database#PublisherConfirms#Publisher#Confirms#Exist#Mandatory#StudyNotes#SkillVeris