Clustering & High Availability
Classic mirrored queues vs quorum queues, and what actually happens to messages when a node fails.
Why a single broker isn't enough
Every example so far in this track has run against one RabbitMQ node. That's fine for development, but a single node is also a single point of failure — if it goes down, every queue on it, and every message still sitting in those queues, becomes unavailable until it comes back. A RabbitMQ cluster joins multiple nodes together so the broker as a whole survives an individual node failure, but joining nodes into a cluster only replicates metadata (which exchanges, queues, and bindings exist) across every node by default — it does not, on its own, replicate a queue's actual messages anywhere beyond the one node that queue happens to live on. Getting message-level redundancy requires explicitly choosing a replicated queue type.
Classic mirrored queues (legacy)
RabbitMQ's original answer to queue redundancy: a mirrored queue designates one node as the master and replicates every message to mirror nodes on one or more other nodes as it arrives.
# Legacy policy-based mirroring — sets up mirrors across all nodes in the cluster
rabbitmqctl set_policy ha-all "^orders\." '{"ha-mode":"all"}'
If the master node fails, a mirror is promoted to take over — but classic mirroring has two well-known weaknesses that led RabbitMQ to deprecate it in favor of quorum queues: the replication protocol doesn't guarantee mirrors are fully caught up before a promotion, so a failover can silently lose messages that were acknowledged by the master but hadn't yet reached every mirror, and a network partition can produce genuinely inconsistent behavior depending on the partition-handling strategy configured. Classic mirrored queues remain supported for backward compatibility but are not the recommended choice for new deployments.
Quorum queues (the modern default)
Quorum queues replace mirrored queues as RabbitMQ's recommended high-availability queue type, built on the Raft consensus algorithm — the same family of protocol used by systems like etcd and CockroachDB for replicated, fault-tolerant state.
const amqp = require('amqplib');
async function declareQuorumQueue() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertQueue('orders.queue', {
durable: true,
arguments: {
'x-queue-type': 'quorum',
},
});
}
A quorum queue's replicas elect a leader, and every write is only considered successful once a majority of replicas have durably persisted it — not just the leader. That single design choice is what fixes classic mirroring's core weakness: a message acknowledged as written is guaranteed to already exist on a majority of replicas, so no failover can silently lose it.
What happens on node failure
With a quorum queue spread across, say, three nodes:
Before failure:
Node A (leader) -- has message X, published and confirmed
Node B (follower) -- has message X (replicated before the publish was confirmed)
Node C (follower) -- has message X (replicated before the publish was confirmed)
Node A crashes:
Node B and Node C detect the leader is gone, hold a Raft leader election
Node B (say) becomes the new leader — it already has message X, nothing lost
Node A comes back:
Rejoins as a follower, catches up on anything it missed while it was down
As long as a majority of replicas (2 out of 3, in this example) remain reachable, the queue keeps accepting publishes and deliveries throughout the failure, with a brief pause only for the leader election itself. If a majority is not reachable — a 3-node quorum queue losing 2 of its 3 nodes at once — the queue stops accepting writes entirely rather than risk an inconsistent state; it comes back automatically the moment enough replicas rejoin.
Comparing the two
| Classic mirrored queues | Quorum queues | |
|---|---|---|
| Replication protocol | Custom RabbitMQ mirroring | Raft consensus |
| Write acknowledged only after majority durably has it | No | Yes |
| Risk of silent message loss on failover | Yes, under certain failure/partition scenarios | No — a majority already has any acknowledged write |
| Status | Deprecated, legacy support only | Recommended default for new deployments |
| Configuration | A policy (ha-mode) applied after the fact |
An argument (x-queue-type: quorum) set at declaration time |
Common mistakes
- Assuming joining nodes into a cluster automatically makes every queue highly available — clustering alone only replicates exchange/queue/binding definitions; a queue's actual messages live on whichever single node hosts it unless it's explicitly declared as mirrored or quorum.
- Choosing classic mirrored queues for a new system in 2026 instead of quorum queues — mirroring is legacy, kept only for backward compatibility, and carries a real risk of silent message loss on failover that quorum queues were built specifically to eliminate.
- Running a cluster with an even number of nodes — Raft-based quorum queues need a clear majority to make progress, and an even split makes a tie (and a stalled queue) more likely during a network partition than an odd node count would.
- Not planning for what happens when a majority of a quorum queue's replicas are unreachable — the queue deliberately stops accepting writes in that scenario rather than risking inconsistency, which is correct behavior, not a bug, but needs to be understood before it happens in production.