Broker Semantics

Here we describe the broker semantics. This should be read together
with the AMQP specification.

Semantics of tx

The semantics of AMQP's tx class, as defined in
AMQP 0-9-1, and its implementation in different versions of
the RabbitMQ server, is often misunderstood. Here is a
summary of the behaviour:

Feature

AMQP0-9-1

RabbitMQ< 2.6.0

RabbitMQ2.6.0-2.7.1

RabbitMQ>= 2.8.0

transactional basic.publish

yes

yes

yes

yes

transactional basic.ack

yes

yes

yes

yes

transactional basic.reject

no

no

no

yes

transactional exchange/queue/binding creation/deletion

no

no

no

no

transactional consuming/getting of messages

no

no

no

no

atomicity in single queue

yes

no

no

no

atomicity across multiple queues

no

no

no

no

error detection (e.g. invalid exchange)

undefined

immediate

immediate

immediate

sending of 'no_route' basic.return

undefined

immediate

on commit

on commit

effect visibility / responsibility transfer / durability

undefined

on commit

on commit

on commit

Overall the behaviour of the AMQP tx class, and
more so its implementation on RabbitMQ, is closer to
providing a 'batching' feature than ACID capabilities known
from the database world.

AMQP transactions only apply to publishes and acks. We have
additionally made rejection transactional. Other operations
such as resource creation/deletion are not
transactional. Consequently the behaviour of
transactions when any of the involved exchanges, queues or
bindings are altered is undefined.

On the consuming side, the acknowledgements are
transactional, not the consuming of the messages
themselves. Hence no requeuing of consumed messages takes
place on rollback; the client can still ack/reject these
messages in subsequent transactions.

AMQP guarantees atomicity only when transactions involve a
single queue, i.e. all the publishes inside the tx get
routed to a single queue and all acks relate to messages
consumed from the same queue. When multiple queues are
involved it is possible that in the event of a broker
failure during tx.commit the effects of the
transaction are only visible in some of the
queues. Furthermore, RabbitMQ provides no atomicity
guarantees even in case of transactions involving just a
single queue, e.g. a fault during tx.commit can
result in a sub-set of the transaction's publishes appearing
in the queue after a broker restart.

AMQP does not specify when errors (e.g. lack of permissions,
references to unknown exchanges) in
transactional basic.publish
and basic.ack commands should be
detected. RabbitMQ performs the necessary checks immediately
(rather than, say, at the time of commit), but note that
both basic.publish and basic.ack
are asynchronous commands so any errors will be reported
back to the client asynchronously.

The situation is similar with basic.returns,
though note the slight change in behaviour between earlier
and recent versions of RabbitMQ. You will always receive
any basic.returns before
the tx.commit-ok.

AMQP does not specify when the effects of transactions
should become visible following a tx.commit,
e.g. when published messages will appear in queues and can
be consumed from other clients, when persistent messages
will be written to disk, etc. In RabbitMQ
the tx.commit-ok indicates that all
transaction effects are visible and that the broker has
accepted responsibility for all the messages published in
the transaction.

For acknowledgements, the receipt of a
tx.commit-ok is an indicator that the
acknowledgements have been received by the server,
not that they have been processed, persisted,
etc. Consequently it is possible for a subsequent
server-side failure to "resurrect" the acknowledged
messages, and for consuming clients to receive them again.

Message ordering guarantees

Section 4.7 of the AMQP 0-9-1 core specification explains the
conditions under which ordering is guaranteed: messages
published in one channel, passing through one exchange and
one queue and one outgoing channel will be received in the
same order that they were sent. RabbitMQ offers stronger
guarantees since release 2.7.0.

Messages can be returned to the queue using
AMQP methods that feature a requeue parameter
(basic.recover, basic.reject and
basic.nack), or due to a channel closing while
holding unacknowledged messages. Any of these scenarios
caused messages to be requeued at the back of the queue
for RabbitMQ releases earlier than 2.7.0. From RabbitMQ
release 2.7.0, messages are always held in the queue in
publication order, even in the presence of requeueing or
channel closure.

With release 2.7.0 and later it is still possible for
individual consumers to observe messages out of order if
the queue has multiple subscribers. This is due to the
actions of other subscribers who may requeue messages. From
the perspective of the queue the messages are always held
in the publication order.

Exclusive queues, durability and mirroring

An exclusive queue is one which is deleted whenever the connection
that declares it is closed. Although AMQP 0-9-1 allows you to
declare a durable exclusive queue, the durability is meaningless
since the queue will vanish anyway as soon as the broker
stops. Therefore RabbitMQ will ignore the durable flag in a
declaration of an exclusive queue and create an exclusive transient
queue.

Similarly, there is no benefit to mirroring an exclusive queue,
since such a queue will be deleted when the node it was declared on
shuts down. Therefore RabbitMQ will never mirror exclusive queues.