Why RabbitMQ?
In any system with multiple services, there comes a point where synchronous communication (Service A directly calls Service B and waits) becomes a bottleneck. RabbitMQ solves this by introducing an intermediary message broker:
- Service A publishes a message to a queue.
- Service B consumes the message when it’s ready.
- If Service B is down, the message waits safely in the queue until B comes back.
This pattern—known as asynchronous messaging—is the foundation of scalable microservice architectures.
Prerequisites
- A Linux server (Ubuntu 22.04 or RHEL 9).
- At least 2 GB RAM (RabbitMQ runs on the Erlang VM).
- Root or sudo access.
Step 1: Install RabbitMQ
Ubuntu/Debian
# Install Erlang (dependency)
sudo apt install -y erlang-base erlang-nox
# Add RabbitMQ repository
curl -1sLf 'https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey' | sudo gpg --dearmor -o /usr/share/keyrings/rabbitmq.gpg
echo "deb [signed-by=/usr/share/keyrings/rabbitmq.gpg] https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/rabbitmq.list
sudo apt update && sudo apt install rabbitmq-server -y
# Start and enable
sudo systemctl enable --now rabbitmq-server
# Enable Management Plugin (Web UI on port 15672)
sudo rabbitmq-plugins enable rabbitmq_management
Access the management UI at http://your-server:15672 (default: guest/guest, only from localhost).
Create an Admin User
sudo rabbitmqctl add_user admin StrongPassword123
sudo rabbitmqctl set_user_tags admin administrator
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
Step 2: Core Concepts
Exchange Types
| Type | Routing Behavior |
|---|---|
| Direct | Routes to queues whose binding key exactly matches the message’s routing key |
| Fanout | Broadcasts to ALL bound queues (ignores routing key) |
| Topic | Pattern matching with wildcards (*.error, logs.#) |
| Headers | Routes based on message header attributes |
Durable vs Transient
- Durable queues survive broker restarts (messages persist to disk).
- Transient queues are deleted when the broker restarts.
- For production, always use durable queues + persistent messages (
delivery_mode=2).
Step 3: Clustering for High Availability
A single RabbitMQ node is a single point of failure. For production, cluster 3 nodes and use quorum queues.
Join Nodes to a Cluster
# On node2 and node3:
sudo rabbitmqctl stop_app
sudo rabbitmqctl reset
sudo rabbitmqctl join_cluster rabbit@node1
sudo rabbitmqctl start_app
Important: All nodes MUST share the same Erlang cookie:
# Copy from node1 to all other nodes
sudo scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/.erlang.cookie
Quorum Queues (Recommended)
Quorum queues use the Raft consensus protocol for automatic leader election and replication.
# Declare a quorum queue via the management API
rabbitmqadmin declare queue name=orders durable=true arguments='{"x-queue-type":"quorum"}'
Troubleshooting
| Problem | Solution |
|---|---|
| Memory alarm (publishers blocked) | Add consumers, increase RAM, set max-length policy, or enable lazy queues |
| Nodes can’t cluster | Verify .erlang.cookie is identical, hostname resolution works, and port 4369/25672 is open |
| Messages not being consumed | Check consumer connections in management UI; verify queue bindings match routing keys |
| ”Connection refused” from app | Verify port 5672 (AMQP) is open in firewall and RabbitMQ is listening on the correct interface |
| Queue growing unbounded | Set a policy: rabbitmqctl set_policy TTL ".*" '{"message-ttl":86400000}' --apply-to queues (24h TTL) |
Summary
- Use RabbitMQ to decouple services and handle traffic spikes gracefully.
- Always use durable queues + persistent delivery in production.
- For HA, set up a 3-node cluster with quorum queues.
- Monitor via the management UI (port 15672) or Prometheus exporter.