RabbitMQ Publisher Confirms: Know When a Message Is Accepted
Publisher confirms tell a RabbitMQ producer when a message is accepted and routed, without the throughput cost of transactions.
29 Apr 2026, 11:44 UTC

What a publisher confirm actually tells you
You publish a message to RabbitMQ and your application moves on. The broker does not reply by default, so your code has no way to distinguish between "accepted and routed" and "silently dropped." If a queue is missing, a node restarts, or a network failure cuts the connection, the message can disappear without an error reaching the producer.
The useful takeaway is publisher confirms. This is a lightweight, per-channel setting that asks RabbitMQ to send basic.ack or basic.nack after it accepts a message and routes it to a queue—or after a quorum queue replicates it. Confirms do not prove a consumer processed the message, but they close the acceptance gap without the heavy throughput penalty of RabbitMQ transactions.
When a channel enters confirm mode—commonly by calling confirm.select in the client library—the broker assigns a sequence number to every outgoing message on that channel. After RabbitMQ accepts the message and routes it to at least one queue, it sends basic.ack back to the producer. If it cannot route the message, it sends basic.nack. For quorum queues, the confirm waits until the message is replicated across the quorum, not merely accepted by one node.
Confirms are asynchronous. The producer can keep publishing while earlier confirms arrive, matching each incoming frame to its sequence number. This avoids the round-trip wait of synchronous transactions while still giving the producer visibility into broker acceptance.
Confirms versus RabbitMQ transactions
RabbitMQ also offers transactions (tx.select, tx.commit, tx.rollback), but they serve a different purpose and carry a much higher cost. Transactions force synchronous coordination across the publish batch and can sharply reduce throughput.
| Option | What it confirms | Typical cost | When to choose it |
|---|---|---|---|
| Publisher confirms | Broker accepted and routed the message | Low; asynchronous, batched | Most reliable publishing |
| RabbitMQ transactions | A group of publishes committed atomically | High; synchronous coordination | Multi-message atomic commits |
Use confirms for ordinary event publishing, financial events, and state changes where you need to know the broker took the message. Reserve transactions for the rare case where several publishes must succeed or fail together.
Worked example: publishing with confirms
Run this on a developer workstation or CI host that can reach a local RabbitMQ instance. The RabbitMQ user must have publish permissions on the target virtual host. The code below is illustrative; exact method names depend on your client library.
connection = establish_connection("")
channel = connection.channel()
# Enable publisher confirms on this channel.
channel.confirm_delivery()
try:
channel.basic_publish(
exchange="",
routing_key="",
body=b"order-created",
mandatory=True
)
# Wait for the matching confirm frame. Library APIs vary.
confirm = channel.wait_for_confirm()
if confirm.is_ack():
log("broker accepted and routed the message")
else:
log("broker could not route the message")
except UnroutableError:
log("returned because no queue matched the routing key")
finally:
connection.close()
Placeholders like <RABBITMQ_URL> should be replaced with your connection string, including credentials and virtual host. Setting mandatory=True asks RabbitMQ to return unroutable messages instead of dropping them silently.
Expected checks: a routed message produces basic.ack; publishing to an exchange with no matching queue should produce basic.nack or a returned-message error. A risk to track: if the connection drops before the confirm arrives, the producer does not know whether RabbitMQ accepted the message. Your client must keep a list of unconfirmed sequence numbers and decide whether to resend (risking duplicates) or fail the operation.
Limits and how to verify the behavior
Publisher confirms guarantee broker acceptance, not consumer processing. A message can be acknowledged to the producer and still fail at the consumer. End-to-end reliability still requires consumer acknowledgments, durable queues where appropriate, and dead-letter or requeue logic for rejected messages.
Client libraries differ in how they surface confirms, handle timeouts, and recover after channel errors. Check your library’s documentation before assuming retry semantics.
A practical verification is to publish to an exchange with no binding that matches the routing key, using mandatory=True. Your client should receive a nack or returned-message indication rather than a silent success. If you need stronger evidence, publish to a durable queue, stop the broker while confirms are in flight, and observe whether your client resends unconfirmed messages or treats them as failed—then reconcile that behavior with your durability requirements.
What to do next
Enable publisher confirms on channels that publish important events. Pair them with manual consumer acknowledgments and idempotent consumers so duplicates from retries do not corrupt state. Skip RabbitMQ transactions unless you genuinely need atomic commits across multiple publishes. Finally, confirm—literally—that your client library’s confirm and timeout behavior matches your failure model before deploying to production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.