Skip to content

Architecture

Internals of RabbitMQ 4.x: the Erlang/OTP runtime model, the Khepri metadata store, the three queue types (quorum, classic, stream), exchanges, and the federation/shovel plugins.

Component Overview

flowchart TB
    Client["Client (AMQP, MQTT, STOMP, Stream protocol)"]
    subgraph Node["RabbitMQ Node — Erlang VM (BEAM)"]
        ConnSup["Connection supervisor"]
        ChannelSup["Channel supervisor"]
        ProtoHandler["Protocol Handler\n(amqp091, amqp10, mqtt, stomp, stream)"]
        ExchangeRouter["ExchangeRouter"]
        DirectExchange["DirectExchange"]
        TopicExchange["TopicExchange"]
        FanoutExchange["FanoutExchange"]
        HeadersExchange["HeadersExchange"]
        ConsHashEx["Consistent-Hash Exchange (plugin)"]
        QQ["QuorumQueue\n(Raft + log_segments)"]
        ClassicQ["ClassicQueue\n(in-memory + WAL)"]
        Stream["Stream\n(append segments)"]
        Khepri["Khepri\n(Raft metadata)"]
        Mgmt["rabbitmq_management"]
        Prom["rabbitmq_prometheus"]
    end
    Client --> ProtoHandler
    ProtoHandler --> ChannelSup
    ChannelSup --> ExchangeRouter
    ExchangeRouter --> DirectExchange
    ExchangeRouter --> TopicExchange
    ExchangeRouter --> FanoutExchange
    ExchangeRouter --> HeadersExchange
    DirectExchange --> QQ
    TopicExchange --> Stream
    FanoutExchange --> ClassicQ
    HeadersExchange --> QQ
    ConsHashEx --> QQ
    Khepri -.holds.-> ExchangeRouter
    Khepri -.holds.-> QQ
    Khepri -.holds.-> Stream

Components

Component Role
Erlang VM (BEAM) Concurrency model with millions of lightweight processes. Per-connection / per-channel / per-queue processes.
Connection One Erlang process per AMQP TCP connection. Holds heartbeats and channel multiplex state.
Channel Sub-stream within a connection. Cheaper than a TCP connection. Holds prefetch, ack state, transaction state.
Exchange Routing element with no own message storage. Implementation type chosen at declaration.
Binding Edge from Exchange→Queue (or Exchange→Exchange) with optional routing-key + arguments.
Queue (Quorum) Raft-replicated, durable, work-queue oriented.
Queue (Classic) Single-master, persisted via WAL+segment files. Deprecated for replication.
Stream Append-only segment log, Raft-replicated. Optimized for fan-out and high throughput.
Khepri Metadata store: vhosts, users, exchanges, bindings, policies. Raft consensus, replaces Mnesia.
Plugins Federation, Shovel, MQTT, STOMP, Stream, Web-MQTT, Web-STOMP, Delayed Message, Consistent-Hash, OAuth 2.0, LDAP, Top, Tracing.

AMQP 0-9-1 Routing Model

sequenceDiagram
    participant P as Producer
    participant C as Channel
    participant E as Exchange
    participant Q as Queue
    participant Cn as Consumer
    P->>C: basic.publish exchange=X routing_key=k
    C->>E: route(k)
    E->>Q: route by binding (k or pattern)
    Q->>Q: append message
    Q->>Cn: deliver (push) / Cn polls (pull)
    Cn->>Q: basic.ack delivery-tag=N

Exchange types

Type Routing
direct Exact routing key match → bound queue.
topic Pattern routing key with * (one word) and # (zero+ words).
fanout Broadcast to every bound queue.
headers Match on message headers (x-match: all|any).
consistent-hash (plugin) Hash routing key into one of N bound queues — partition-style sharding.
random (plugin) Pick a single bound queue at random.
delayed-message (plugin) Hold messages with x-delay then re-route.

Queue Types Deep Dive

Quorum Queue

sequenceDiagram
    participant P as Producer
    participant L as Leader
    participant F1 as Follower 1
    participant F2 as Follower 2
    participant C as Consumer
    P->>L: publish (channel)
    L->>L: append to Raft log + WAL
    L->>F1: AppendEntries
    L->>F2: AppendEntries
    F1->>L: ack
    F2->>L: ack
    Note right of L: quorum reached
    L->>P: basic.ack confirm
    L->>C: deliver
    C->>L: basic.ack
    L->>F1: replicate ack state
    L->>F2: replicate ack state
  • Built on the Ra Raft library by RabbitMQ team.
  • Snapshots and log compaction prevent unbounded growth.
  • Per-queue tunables: x-delivery-limit, x-max-length, x-max-length-bytes, x-overflow, x-quorum-initial-group-size.
  • 4.x adds continuous queue membership reconciliation so adding/removing nodes rebalances queues automatically.

Classic Queue

  • Single master process. Mirrors are removed in 4.x.
  • Used for ephemeral, exclusive, or auto-delete cases (RPC reply queues).
  • Persistence via WAL + segment files. Supports lazy mode (everything to disk immediately).

Stream

  • Append-only segment files. Consumers read by offset.
  • Raft replication for durability.
  • Pure stream protocol on TCP 5552. AMQP 0-9-1 access also possible (x-queue-type: stream).
  • Use cases: high fan-out (every consumer reads every message), large historical replay.

Khepri (Metadata Store)

Khepri replaces Mnesia for vhost/user/exchange/binding/policy metadata.

Trait Mnesia (legacy) Khepri (4.x)
Consensus Custom (master–master quorum, partition strategy) Raft
Network partition Required pause_minority / autoheal Built-in: minority becomes read-only
Schema migrations Manual + brittle Versioned, auto-applied
Tooling rabbitmqctl over Mnesia rabbitmqctl over Khepri (transparent)

In 4.0 Khepri was opt-in. In 4.2+ Khepri is the default. Mnesia removal scheduled for a future major release.

Federation Plugin

Federation forwards messages between two RabbitMQ deployments by subscribing to upstreams and republishing to local exchanges/queues. Latency-tolerant. Suitable for cross-region.

flowchart LR
    UpstreamRabbit["Upstream RabbitMQ\n(US)"]
    DownstreamRabbit["Downstream RabbitMQ\n(EU)"]
    UpstreamEx["UpstreamExchange"]
    DownstreamEx["DownstreamExchange"]
    UpstreamRabbit --> UpstreamEx
    UpstreamEx -. federation link .-> DownstreamEx
    DownstreamEx --> DownstreamRabbit

Shovel Plugin

Shovel is a one-off message mover: fetch from source, publish to destination. Useful for migration windows or burning off backlog into a different broker.

Connection / Channel Lifecycle

stateDiagram-v2
    [*] --> TCP: open
    TCP --> Authenticated: SASL
    Authenticated --> ChannelOpen: channel.open
    ChannelOpen --> Idle
    Idle --> Publishing: basic.publish
    Idle --> Consuming: basic.consume
    Publishing --> Idle: confirm/return
    Consuming --> Idle: cancel
    ChannelOpen --> ChannelClosed: channel.close
    ChannelClosed --> [*]
    Authenticated --> [*]: connection.close

Performance Characteristics

Workload Throughput
Quorum queue, persistent, R3 ~30k–100k msg/sec/queue (NVMe)
Classic queue, persistent ~50k–150k msg/sec/queue
Stream protocol (port 5552), R3 1M+ msg/sec/cluster
MQTT plugin, native ~50k connected clients/node, ~50k pub/sec
Federation cross-WAN Latency = WAN RTT + repeat overhead

Benchmark caveat

These are order-of-magnitude figures from official RabbitMQ blogs and community benchmarks. Always run perf-test on representative hardware.

Comparison hooks

  • vs Kafka — RabbitMQ wins on routing flexibility and AMQP 0-9-1 compatibility. Kafka wins on log replay throughput and analytic ecosystem.
  • vs NATS — NATS wins on latency and footprint. RabbitMQ wins on routing primitives, dead-letter, and protocol breadth.
  • vs Pulsar — Pulsar offers tiered storage and multi-tenancy out of the box. RabbitMQ uses vhosts + plugins for similar boundaries.

Security

RabbitMQ's security model layers AMQP-level authentication, vhost-based authorization, transport-level TLS, and pluggable identity backends.

Authentication

Method Use Case
Internal user database Default. Passwords hashed with SHA-256 (configurable).
OAuth 2.0 / JWT Enterprise SSO via Keycloak, Auth0, Azure AD. The rabbitmq_auth_backend_oauth2 plugin.
LDAP Directory-based identity. The rabbitmq_auth_backend_ldap plugin.
mTLS (x509) Cert-based auth via the rabbitmq_auth_mechanism_ssl plugin. CN/SAN maps to user.
HTTP backend Custom auth via REST endpoint. The rabbitmq_auth_backend_http plugin.
Cache backend Wrap any other backend with caching to reduce per-connection cost.

OAuth 2.0 with introspection

# rabbitmq.conf
auth_backends.1 = rabbit_auth_backend_oauth2
auth_oauth2.resource_server_id = rabbitmq
auth_oauth2.preferred_username_claims.1 = preferred_username
auth_oauth2.scope_aliases.read = read:orders
auth_oauth2.scope_aliases.write = write:orders
auth_oauth2.discovery_endpoint = https://idp.example.com/.well-known/openid-configuration
auth_oauth2.signing_keys = /etc/rabbitmq/jwt-keys

The plugin verifies the JWT, derives the user, and checks scopes for vhost permissions.

Authorization

Permissions are vhost-scoped triples (configure, write, read) — each is a regex matching resource names.

rabbitmqctl set_permissions -p /prod orders-svc '^orders\.' '^orders\.' '^orders\.'
rabbitmqctl set_topic_permissions -p /prod orders-svc amq.topic '^orders\.' '^orders\.'
Permission Applies To
configure Declare/delete exchanges, queues, bindings, policies.
write Publish to exchanges, route to queues.
read Consume from queues, examine bindings.

User tags grant management UI roles: administrator, monitoring, policymaker, management.

Encryption

In transit

  • TLS for AMQP (:5671), AMQP 1.0, MQTT (:8883), STOMP (:61614), Stream (:5552 over TLS), management (:15672 HTTPS), Prometheus (:15692 HTTPS), Erlang inter-node (set via inet_dist_use_interface + RABBITMQ_CTL_ERL_ARGS).
  • mTLS supported on every listener.
  • Verify CRL and OCSP separately if the deployment requires real-time revocation.
listeners.ssl.default = 5671
ssl_options.cacertfile = /etc/rabbitmq/certs/ca.pem
ssl_options.certfile   = /etc/rabbitmq/certs/server.pem
ssl_options.keyfile    = /etc/rabbitmq/certs/server.key
ssl_options.verify     = verify_peer
ssl_options.fail_if_no_peer_cert = true
ssl_options.versions.1 = tlsv1.3
ssl_options.versions.2 = tlsv1.2

Inter-node Erlang distribution

Erlang's distribution protocol must be on a private network or wrapped in inet_tls_dist. Default magic cookie is not a security boundary.

At rest

RabbitMQ does not encrypt queue/segment files on disk. For at-rest encryption use OS-level dm-crypt or cloud-provider EBS/Persistent-Disk encryption.

Audit & Observability

  • Logs: /var/log/rabbitmq/rabbit@<node>.log records auth attempts and permission denials.
  • Tracing: the rabbitmq_tracing plugin captures every published/consumed message into a trace queue.
  • Federation/Shovel parameters do not log credentials by default — verify that your config logger does not leak uri strings.
  • Audit events: rabbitmq_event_exchange plugin publishes management/connection events to amq.rabbitmq.event.

Threat Model

Threat Mitigation
Default guest account exposed Bound to localhost by default. Keep loopback_users.guest = true.
Management UI on public IP Bind management to private network. Reverse-proxy with auth.
Erlang distribution attack Wrap in inet_tls_dist. Restrict cluster network.
Permission escalation via administrator tag Issue management roles minimally. Rotate them.
Plugin supply chain Pin plugin versions. Install only from rabbitmq-plugins (signed).
MITM on AMQP mTLS on :5671. Reject :5672 in production.
Vhost escape Permissions are enforced at the broker. Make sure that regexes are scoped tightly.
Federation credential theft Use mTLS-only upstreams. Rotate via rabbitmqctl clear_parameter federation-upstream.
Replay attacks At app level: include a nonce. Use the x-message-deduplication plugin where appropriate.
Slow-consumer DoS Combine consumer_timeout, consumer_capacity alarms, and quorum queue x-delivery-limit.
OAuth token replay Set tight token TTLs. Use the audience claim per cluster.
WebSocket / MQTT abuse Rate-limit at ingress (for example, nginx, Traefik). Enforce auth on :1883/:8883.

CVE History (selected)

CVE Year Affected Summary
CVE-2024-50582 2024 rabbitmq_management plugin Reflected XSS in management UI. Fixed in 3.13.7 / 4.0.2.
CVE-2023-46118 2023 rabbitmq-server before 3.12.7 Memory exhaustion via large MQTT message. Fixed by tightening mqtt.max_message_size.
CVE-2023-46118 follow-up 2023 MQTT 5 plugin Hardening of property parsing. Fix in 3.12.x.
CVE-2022-31010 2022 rabbitmq_web_mqtt plugin DoS via crafted WebSocket frame.

Subscribe to the GitHub Security Advisories feed for the canonical list.

Hardening Checklist

  • Disable AMQP plain port (:5672) for production. Require AMQPS.
  • Bind :15672 (mgmt UI) to a private network or behind a reverse proxy with SSO.
  • Replace guest user immediately. Restrict administrator tag holders.
  • Enable OAuth 2.0 + audience-pinned JWTs.
  • mTLS for inter-node Erlang distribution.
  • Rotate federation/shovel credentials via parameter API.
  • Enable rabbitmq_event_exchange and ship events to SIEM.
  • Set cluster_partition_handling = pause_minority (default since 3.6).
  • Set quorum queue x-delivery-limit to bound poison loops.
  • OS-level disk encryption (dm-crypt / cloud KMS) for /var/lib/rabbitmq.
  • Subscribe to RabbitMQ Security Advisories.

Cross-references