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 (:5552over TLS), management (:15672HTTPS), Prometheus (:15692HTTPS), Erlang inter-node (set viainet_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>.logrecords auth attempts and permission denials. - Tracing: the
rabbitmq_tracingplugin 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
uristrings. - Audit events:
rabbitmq_event_exchangeplugin publishes management/connection events toamq.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
guestuser immediately. Restrictadministratortag holders. - Enable OAuth 2.0 + audience-pinned JWTs.
- mTLS for inter-node Erlang distribution.
- Rotate federation/shovel credentials via parameter API.
- Enable
rabbitmq_event_exchangeand ship events to SIEM. - Set
cluster_partition_handling = pause_minority(default since 3.6). - Set quorum queue
x-delivery-limitto bound poison loops. - OS-level disk encryption (dm-crypt / cloud KMS) for
/var/lib/rabbitmq. - Subscribe to RabbitMQ Security Advisories.
Cross-references¶
- messaging/rabbitmq/explanation — for understanding the vhost/exchange/queue scope of every permission.
- messaging/rabbitmq/how-to-guides — for
rabbitmqctland OAuth 2.0 setup commands. - messaging/index — for cross-broker security comparison.