RabbitMQ Introduction

Run RabbitMQ with Docker and use the management UI to inspect exchanges, queues, and message rates.

A quick recap of the broker model

RabbitMQ implements AMQP: producers publish messages to an exchange, which routes them into one or more queues based on routing rules, and consumers read from those queues. Unlike Kafka's log, a message is typically removed from a queue once it's been consumed and acknowledged. The System Design track's Message Queues & Event-Driven Architecture page covers why that model fits classic task queues and request/reply patterns particularly well, and how it compares to Kafka. This page — and the rest of this track — picks up from there and gets hands-on.

Running RabbitMQ with Docker

The management image variant bundles the web UI plugin, which is worth having from the start:

Bash
docker run -d --name rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3.13-management

Or, as a Compose service with a named volume so definitions and messages survive a container restart:

YAML
services:
  rabbitmq:
    image: rabbitmq:3.13-management
    container_name: rabbitmq
    ports:
      - "5672:5672"   # AMQP — this is the port your application clients connect to
      - "15672:15672" # HTTP management UI
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq

volumes:
  rabbitmq-data:

The management UI

Open http://localhost:15672 and log in with the default credentials, guest / guest (which only work for connections originating from localhost — a deliberate safety default). From there you can:

  • Browse every exchange, queue, and the bindings connecting them.
  • Watch live message rates (publish/deliver/ack) per queue — useful for spotting a consumer that's falling behind.
  • Manually publish a test message to any exchange, or pull a message off a queue, without writing any code.
  • Inspect connections and channels — handy for catching a client that opened a connection and never closed it.
  • Set policies (e.g., message TTL, max queue length) across queues matching a name pattern, instead of configuring each one individually.

It's the fastest way to sanity-check that a message actually went where you expected before you start debugging application code.

Common mistakes

  • Exposing port 15672 (or 5672) on a public interface with the default guest/guest credentials still in place — those credentials are well known and only meant to work from localhost by default for exactly this reason.
  • Skipping the named volume in local Compose setups, then losing every queue, exchange, and binding definition on the next docker compose down.
  • Treating the management UI's "publish a test message" feature as a substitute for actually testing your producer code — it exercises the broker, not your serialization, routing key logic, or error handling.