What Is New in RabbitMQ 3.9
RabbitMQ 3.9.0 introduces a major new queue type, runtime updates, and significant improvements for cloud-native deployments. Here's a summary of the key changes.
| Category | Key Changes |
|---|---|
| New Features |
|
| Improvements |
|
| Bug Fixes & Changes |
|
| Dependencies |
|
What are Streams in RabbitMQ 3.9?
Streams are a new persistent and replicated data structure, implemented as a queue type. They model an append-only log with non-destructive consumer semantics.
This enables messaging patterns that were difficult before, like repeatable consumption and mass fanouts to thousands of consumers. While you can use Streams via AMQP 0-9-1, a new binary protocol plugin and dedicated clients (Java, Go) are provided for optimal throughput and access to stream-specific operations.
Key Characteristics of Streams
- Durable & Replicated: Data is persisted and replicated across cluster nodes for fault tolerance.
- Non-Destructive Consumption: Consumers can read messages without removing them, allowing multiple independent reads.
- High-Throughput Protocol: A dedicated binary protocol is available for maximum performance.
Why does Erlang 24 support matter for performance?
RabbitMQ 3.9.0 requires Erlang 23.2 or later and fully supports Erlang 24, which is now the default in the community Docker image. This runtime upgrade is a big deal for throughput.
Tests by the core team and community show Erlang 24 provides 20% to 50% higher throughput for many common workloads. This is a free performance boost just by upgrading your runtime. The new Erlang version also allowed the team to drop some external dependencies in favor of built-in libraries.
If you're on an older Erlang version (pre-23.2), you must first upgrade to RabbitMQ 3.8.16+ on Erlang 23.2, then upgrade to 3.9.0 and ideally to Erlang 24.
How does RabbitMQ 3.9 improve Kubernetes deployments?
The improvements focus on faster, more reliable cluster formation and better integration with the official Kubernetes operators.
The built-in Kubernetes peer discovery plugin no longer uses randomized startup delays. Instead, it uses an internal distributed locking mechanism available in Erlang 23.2+. This eliminates a race condition during parallel pod startup, ensuring only one initial cluster forms reliably and faster.
The open-source RabbitMQ Cluster Operator automates cluster provisioning and management, while the Messaging Topology Operator lets you define exchanges, queues, and users as Kubernetes resources. These work with 3.8.x but are optimized for the 3.9 series.
What changed with logging and monitoring?
Logging has been overhauled. RabbitMQ now uses the standard Erlang Logger API instead of the third-party Lager framework. This enables structured logging in JSON format, which is much easier to parse and integrate with log aggregation systems like the Elastic stack.
On the metrics side, message rates are now broken down per protocol (AMQP, MQTT, STOMP) and per queue type (classic, quorum, stream) in Prometheus output. This gives operators much finer-grained visibility into traffic patterns. It also fixes some counter issues present in 3.8.x.
What are the other notable changes and fixes?
Beyond the headlines, several under-the-hood enhancements improve stability and operability.
- Faster Recovery: Binding recovery on node startup is more efficient, speeding up restarts in topologies with many bindings.
- Quorum Queue Federation: The Federation plugin now supports quorum queues.
- Management API Change: User tags in the HTTP API are now exported as a JSON list. The server can still import the old comma-separated format for compatibility.
- Classic Queue Mirroring: Mirrored queue replicas now start synchronously, improving consistency during failover.
A number of bugs were fixed, including issues with queue index recovery after a crash, SSL acceptor configuration, and Management UI quirks.
FAQ
Can I upgrade directly from RabbitMQ 3.8.15 to 3.9.0?
No. RabbitMQ 3.9.0 requires Erlang 23.2 or later. You must first upgrade to RabbitMQ 3.8.16+ on Erlang 23.2, then upgrade to 3.9.0. A direct upgrade from older 3.8.x releases on older Erlang will fail.
Are Streams a replacement for Classic or Quorum Queues?
No, they are a complementary queue type designed for different use cases. Streams are ideal for auditing, event sourcing, and fanout to many consumers where message retention and replay are needed. Classic and Quorum queues remain the best choice for traditional task queue patterns.
What happens in a mixed-version cluster (3.8.x and 3.9.0)?
While rolling upgrades are supported, some 3.9-specific features (like Streams) won't be available until all nodes are upgraded. Also, declaring new quorum queues may fail if attempted from a node running the minority version, and the HTTP API may return limited classic queue metrics. Run mixed clusters only for the short duration of the upgrade.
I use the Management API. What do I need to change for user tags?
The HTTP API now returns user tags as a JSON array (e.g., ["management", "policymaker"]) instead of a comma-separated string. Your client library may need updating to handle both formats. RabbitMQ 3.9 can still import definitions using the old string format.
Does the new JSON logging replace the existing text format?
No, it's an option. You can configure the node to log in either traditional plain text or structured JSON format. The JSON format is particularly useful if you pipe logs into systems like Prometheus or Elasticsearch for alerting and analysis.