title: Regarding message order guarantees in RabbitMQ/AMQP
body: <p>One of the main characteristics of a message queue service, RabbitMQ included, is preserving message publication order. This is confirmed in the <a href="https://www.rabbitmq.com/semantics.html#ordering" rel="nofollow noreferrer">RabbitMQ documentation</a>:</p>
  <blockquote>
  <p><strong>[QUOTE 1]</strong> 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.</p>
  </blockquote>
  <p>Let's assume in the following that there are no consumers active, to simplify things. We are publishing over one single channel.</p>
  <p>So far, so good.</p>
  <p>RabbitMQ also provides possibility to inform the publisher that a certain publication has been completely and correctly processed <strong>[*]</strong>. This is explained <a href="https://www.rabbitmq.com/confirms.html#publisher-confirms" rel="nofollow noreferrer">here</a>. Basically, the broker will either send a <code>basic.ack</code> or <code>basic.nack</code> message. The documentation also says this:</p>
  <blockquote>
  <p><strong>[QUOTE 2]</strong> <code>basic.ack</code> for a persistent message routed to a durable queue will be
  sent after persisting the message to disk.</p>
  <p>In most cases, RabbitMQ will acknowledge messages to publishers in the
  same order they were published (this applies for messages published on
  a single channel). However, publisher acknowledgements are emitted
  asynchronously and can confirm a single message or a group of
  messages. The exact moment when a confirm is emitted depends on the
  delivery mode of a message (<strong>persistent vs. transient</strong>) and the
  properties of the queue(s) the message was routed to (see above).
  Which is to say that different messages can be considered ready for
  acknowledgement at different times. This means that acknowledgements
  can arrive in a different order compared to their respective messages.
  Applications should not depend on the order of acknowledgements when
  possible.</p>
  </blockquote>
  <p>At first glance, this makes sense: persisting a message takes much more time than just storing it in memory, so it's perfectly possibly that the acknowledgment of a later transient message will arrive before the acknowledgement of an earlier persistent message.</p>
  <p>But, if we re-read the first quote regarding message order <strong>[QUOTE 1]</strong>  here above, it gets confusing. I'll explain. Assume we are sending two messages to the same exchange: first a persistent and then a transient message. Since RabbitMQ claims to preserve message order, how can it send an acknowledgment of the second/transient message before it knows that the first/persistent message is indeed completely written to disk?</p>
  <p>In other words, does the remark regarding illogical acknowledgement order <strong>[QUOTE 2]</strong>  here above only apply in case the two messages are each routed to completely different target queue(s) (which might happen if they have different routing keys, for example)? In that case, we don't have to guarantee anything as done in <strong>[QUOTE 1]</strong>.</p>
  <p><strong>[*]</strong> In most cases, this means 'queued'. However, if there are no routing rules applicable, it cannot be enqueued in a target queue. However, this is still a positive outcome regarding publication confirmation.</p>
  <p><strong>update</strong></p>
  <p>I read this <a href="https://stackoverflow.com/a/35686609/8870331">answer</a> on a similar question. This basically says that there are no guarantees whatsoever. Even the most naive implementation, where we delay the publication of message 2 to the point after we got an acknowledgment of message 1, might not result in the desired message order. Basically, <strong>[QUOTE 1]</strong> is not met.</p>
  <p>Is this correct?</p>