Skip to main content

RabbitMQ Federation Plugin

Introduction

The RabbitMQ Federation Plugin is a powerful extension that allows you to connect multiple RabbitMQ brokers (servers) across different locations, data centers, or network segments. Unlike clustering, which requires brokers to be on the same network with low latency, federation creates looser connections optimized for high-latency or unreliable networks.

Federation enables message producers in one location to seamlessly publish messages that can be consumed by subscribers in different geographic locations, without requiring consumers to connect to distant brokers.

What is Federation?

Federation creates links between brokers where messages published to an exchange in one broker can be automatically transferred to exchanges in other brokers. Similarly, queues in one broker can receive messages from queues in other brokers.

Think of federation as a system of "upstream" and "downstream" relationships:

Federation vs. Clustering

Before diving deeper, let's understand how federation differs from RabbitMQ clustering:

FeatureFederationClustering
Network requirementsWorks across WANs, firewallsRequires LAN, low latency
TopologySelective message sharingAll definitions shared
Failure handlingIndependent brokersCluster-wide impact
Message replicationOnly selected messagesComplete replication
Setup complexitySimpler to configureMore complex

Enabling the Federation Plugin

The federation plugin is included in the RabbitMQ distribution but needs to be enabled:

bash
# Enable the plugin
rabbitmq-plugins enable rabbitmq_federation

# Also enable the management UI for federation
rabbitmq-plugins enable rabbitmq_federation_management

After enabling, restart your RabbitMQ server to apply the changes.

Configuring Federation

Federation configuration involves a few key steps:

Step 1: Define an Upstream

First, define which remote broker(s) you want to connect to. This is done by creating an "upstream" configuration:

bash
# Using rabbitmqctl
rabbitmqctl set_parameter federation-upstream my-upstream \
'{"uri":"amqp://guest:guest@remote-host:5672", \
"ack-mode":"on-confirm", \
"prefetch-count":1000}'

Or through the management UI:

  1. Go to Admin > Federation Upstreams
  2. Click "Add a new upstream"
  3. Fill in the form with your upstream details

Step 2: Set Up a Federation Policy

Next, create a policy that determines which exchanges or queues should be federated:

bash
# Federation policy for exchanges
rabbitmqctl set_policy --apply-to exchanges \
exchange-federation "^federated\." \
'{"federation-upstream-set":"all"}'

# Federation policy for queues
rabbitmqctl set_policy --apply-to queues \
queue-federation "^federated\." \
'{"federation-upstream-set":"all"}'

This example policy federates all exchanges and queues whose names start with "federated.".

Exchange Federation Example

Let's see a practical example of exchange federation using Python with the Pika library:

python
# Producer code (on upstream broker)
import pika

# Connect to the local RabbitMQ server
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# Create a federated exchange
channel.exchange_declare(exchange='federated.topic',
exchange_type='topic',
durable=True)

# Publish a message
routing_key = 'user.created'
message = '{"id": 123, "name": "John Doe"}'
channel.basic_publish(
exchange='federated.topic',
routing_key=routing_key,
body=message,
properties=pika.BasicProperties(
content_type='application/json',
delivery_mode=2 # make message persistent
))

print(f" [x] Sent '{routing_key}': {message}")
connection.close()
python
# Consumer code (on downstream broker)
import pika, json

# Connect to the local broker (which receives federated messages)
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# Make sure the exchange exists (will receive from upstream)
channel.exchange_declare(exchange='federated.topic',
exchange_type='topic',
durable=True)

# Create a queue and bind it
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel.queue_bind(
exchange='federated.topic',
queue=queue_name,
routing_key='user.#') # Subscribe to all user events

print(' [*] Waiting for messages. To exit press CTRL+C')

def callback(ch, method, properties, body):
data = json.loads(body)
print(f" [x] Received {method.routing_key}: {data}")
ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(
queue=queue_name,
on_message_callback=callback)

channel.start_consuming()

In this example:

  1. The producer publishes to a topic exchange named 'federated.topic' on the upstream broker
  2. The federation plugin automatically forwards messages to the same-named exchange on downstream brokers
  3. Consumers on the downstream broker receive messages as if they were published locally

Queue Federation

Queue federation allows messages to be moved from queues in one broker to queues in another broker:

The downstream queue acts as a consumer of the upstream queue, pulling messages across the federation link.

Queue Federation Example

Set up a federated queue:

bash
# On the downstream broker
rabbitmqctl set_parameter federation-upstream upstream-broker \
'{"uri":"amqp://guest:guest@upstream-host:5672"}'

rabbitmqctl set_policy --apply-to queues queue-federation \
"^federated\." '{"federation-upstream":"upstream-broker"}'

Now, any queue matching the pattern federated.* will pull messages from its counterpart on the upstream broker.

Federation Parameters and Tuning

Federation offers several parameters for fine-tuning:

ParameterDescriptionDefault
prefetch-countMaximum number of unacknowledged messages1000
reconnect-delayTime in seconds to wait after failed connection5
ack-modeAcknowledgment mode (on-confirm, on-publish, no-ack)no-ack
trust-user-idWhether to trust user IDs from upstreamfalse
max-hopsMaximum number of federation hops for a message1

Example of setting multiple parameters:

bash
rabbitmqctl set_parameter federation-upstream production-broker \
'{"uri":"amqp://user:pass@prod-host:5672", \
"prefetch-count":2000, \
"reconnect-delay":10, \
"ack-mode":"on-confirm", \
"max-hops":2}'

Multi-Datacenter Topology Example

Let's consider a real-world scenario where you have three data centers and want to set up a hub-and-spoke federation model:

Implementation steps:

  1. On DC2 and DC3, configure DC1 as an upstream:

    bash
    rabbitmqctl set_parameter federation-upstream primary-dc \
    '{"uri":"amqp://user:pass@dc1-host:5672"}'
  2. Set up federation policies:

    bash
    # On DC2 and DC3
    rabbitmqctl set_policy --apply-to exchanges \
    federate-global "^events\.global$" \
    '{"federation-upstream":"primary-dc"}'
  3. Configure local message routing:

    python
    # On each DC, set up binding from global to local exchange
    channel.exchange_declare(exchange='events.local',
    exchange_type='topic',
    durable=True)
    channel.exchange_bind(
    destination='events.local',
    source='events.global',
    routing_key='#.local.#')

This setup allows global events to flow from DC1 to all data centers, while each data center can also handle local-only events.

Monitoring Federation Status

You can monitor federation links through the RabbitMQ Management UI or via HTTP API:

  1. In the Management UI, go to "Admin" > "Federation Status"
  2. Via HTTP API: GET /api/federation-links

The output includes information such as:

  • Status (running, starting, etc.)
  • Message rates (messages/sec)
  • Number of messages in transit
  • Last time the link was active

Troubleshooting Federation

Common federation issues and their solutions:

  1. Links not establishing

    • Check network connectivity between brokers
    • Verify credentials in the URI
    • Ensure the federation plugin is enabled on both brokers
  2. Messages not flowing

    • Check that your federation policy pattern matches your exchange/queue names
    • Verify that bindings exist on the downstream broker
    • Check the upstream exchange type (topic, fanout, etc.) is compatible
  3. Poor performance

    • Increase prefetch-count for higher throughput
    • Consider using on-publish acknowledgment mode for lower latency
    • If messages are large, consider compression or message optimization

Summary

The RabbitMQ Federation Plugin provides a flexible, robust way to connect multiple RabbitMQ brokers across different locations. Unlike clustering, federation is designed for high-latency, unreliable networks, making it ideal for geographically distributed systems.

Key takeaways:

  • Federation connects brokers across WANs and different networks
  • It selectively shares messages between brokers without full replication
  • Configuration involves setting up upstreams and policies
  • Both exchanges and queues can be federated
  • Federation is simpler to set up than clustering for distributed deployments

Exercise: Setting Up a Simple Federation

Try this exercise to practice federation:

  1. Set up two RabbitMQ instances (can be on the same machine with different ports)
  2. Enable the federation plugin on both
  3. Configure the second instance to federate from the first
  4. Create a federated exchange and test publishing/consuming across the federation link
  5. Monitor the federation status in the management UI

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)