RabbitMQ’s federation plugin doesn’t actually create a single, unified cluster; it’s more like a smart mirroring system that lets separate clusters share queues and exchanges.
Let’s see this in action. Imagine we have two RabbitMQ clusters, cluster-a and cluster-b. On cluster-a, we have a standard exchange named upstream-exchange. We want queues on cluster-b to automatically receive messages published to upstream-exchange on cluster-a.
First, on cluster-b, we need to set up a federation upstream. This is essentially a named connection profile that cluster-b will use to talk to cluster-a.
On cluster-b, in the RabbitMQ management UI (usually at http://<cluster-b-node>:15672), navigate to "Admin" -> "Federation Upstreams". Click "Add new upstream".
- Name:
upstream-to-a(This is just a label for this connection oncluster-b) - URI:
amqp://user:password@<cluster-a-node-ip>:5672/(Replaceuser,password, and<cluster-a-node-ip>with your actual credentials and the IP address of a node incluster-a. The virtual host/is assumed. If you use a different vhost, specify it here.) - Trust Management: For simplicity, let’s select "None". In production, you’d configure proper certificate validation.
- Message TTL: Leave blank for now.
- Expires: Leave blank for now.
Click "Add upstream". Now, cluster-b knows how to reach cluster-a.
Next, we set up a federation policy on cluster-b. This policy tells cluster-b what to federate. Navigate to "Admin" -> "Policies" and click "Add/update a policy".
- Name:
federate-from-a - Pattern:
^upstream-exchange$(This regular expression matches the name of the exchange oncluster-awe want to federate. It will create a federated exchange oncluster-bwith the same name.) - Apply to:
exchanges(We are federating an exchange.) - Priority:
0(Higher numbers have higher precedence if patterns overlap.) - Definition:
federation-upstream:upstream-to-a(This links the policy to the upstream connection we just defined.)federation-upstream-set: (Leave blank unless you’re using upstream sets for load balancing.)
Click "Add policy".
Now, on cluster-a, publish a message to upstream-exchange. For example, using rabbitmqadmin:
rabbitmqadmin publish exchange=upstream-exchange routing_key=test_key body="Hello from cluster A!"
On cluster-b, create a queue named downstream-queue and bind it to the upstream-exchange with the routing key test_key.
rabbitmqadmin declare queue name=downstream-queue binding_exchange=upstream-exchange binding_routing_key=test_key
If you check the queues on cluster-b in the management UI, you’ll see downstream-queue. If you then consume a message from downstream-queue on cluster-b, you’ll receive "Hello from cluster A!". The federation plugin on cluster-b automatically created a federated exchange named upstream-exchange and a federated queue downstream-queue (because the policy pattern matched the exchange and we bound a queue to it).
The core problem this solves is distributed messaging where you might have geographically separate RabbitMQ instances, or you want to isolate different services or tenants while still allowing them to share specific message flows. It avoids the complexity and potential single points of failure of trying to make entirely separate clusters behave as one monolithic cluster.
Internally, the federation plugin works by establishing a dedicated AMQP connection from the federating node (e.g., cluster-b) to the upstream node (e.g., cluster-a). It then uses this connection to monitor the upstream for declared entities (exchanges, queues) that match the policy’s pattern. When a match is found, it declares a corresponding entity on the local node (e.g., cluster-b). For exchanges, it sets up a binding from the local federated exchange to the upstream exchange. For queues, it creates a federated queue that mirrors the upstream queue. Messages published to the upstream exchange (and routed to the federated exchange) are then forwarded over the established AMQP connection to the federated queue.
A crucial detail most people miss is that federation is one-way by default. If you publish messages to the federated exchange on cluster-b (upstream-exchange in our example), those messages will not automatically be sent back to cluster-a. To achieve bidirectional communication, you would need to configure a separate federation policy on cluster-a pointing to cluster-b as its upstream.
The next concept you’ll likely encounter is federation upstream sets, which allow you to define multiple upstream connections for a single policy, enabling load balancing and failover across different upstream clusters.