<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>RabbitMQ Blog</title>
        <link>https://www.rabbitmq.com/blog</link>
        <description>RabbitMQ Blog</description>
        <lastBuildDate>Fri, 26 Sep 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Delivery Optimization for RabbitMQ Streams]]></title>
            <link>https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization</link>
            <guid>https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization</guid>
            <pubDate>Fri, 26 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ Streams are designed for high-throughput scenarios, but what happens when your ingress rate is low?]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ Streams are designed for high-throughput scenarios, but what happens when your ingress rate is low?
Low message rates can significantly impact delivery performance, reducing message consumption rates by an order of magnitude.
RabbitMQ 4.2 introduces an optimization that dramatically improves delivery rates for low-throughput streams, benefiting all supported protocols.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="publish-store-consume-with-streams">Publish, Store, Consume with Streams<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#publish-store-consume-with-streams" class="hash-link" aria-label="Direct link to Publish, Store, Consume with Streams" title="Direct link to Publish, Store, Consume with Streams" translate="no">​</a></h2>
<p>When a publishing application sends messages to a RabbitMQ stream using the stream protocol, the client library batches them together into a publishing frame.
RabbitMQ receives these messages and aggregates them, often combining messages from multiple publishers into a single unit of storage, a "<a class="" href="https://www.rabbitmq.com/docs/next/stream-filtering#on-disk-stream-layout">chunk</a>".
This chunk of messages is then stored durably on the file system.</p>
<p>When a consumer subscribes to a stream using the stream protocol, RabbitMQ dispatches messages by sending them in sequential chunks over the network.
The number of messages packed into each chunk - the chunk size - is a critical factor for throughput; large chunks containing hundreds of messages each lead to high message delivery rates for consumers.</p>
<p><em>The ingress rate is the major factor in the chunk size: the higher the ingress rate, the greater the chunk size.
Streams have been designed for high throughput since the beginning.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-problem-with-small-chunks">The Problem With Small Chunks<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#the-problem-with-small-chunks" class="hash-link" aria-label="Direct link to The Problem With Small Chunks" title="Direct link to The Problem With Small Chunks" translate="no">​</a></h2>
<p>What happens when the ingress rate is low?
Chunks will contain just a few messages each—or even a single message in the worst case.
This eliminates the benefits of batching: each frame delivers only a few messages to the consumer.
While chunk dispatching is optimized, it still requires several system calls (reading the file system and writing to the socket).</p>
<p>It is hard to give definitive numbers, but let's say a stream consumer can read several million messages per second from a stream with a chunk size of 300.
The rate can drop to about 200,000 messages per second with a chunk size of 15.
The ratio is what matters here, not the absolute numbers.</p>
<p>Luckily there are ways to make things better with small chunks.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="optimization-for-small-chunks-read-ahead">Optimization For Small Chunks: Read Ahead<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#optimization-for-small-chunks-read-ahead" class="hash-link" aria-label="Direct link to Optimization For Small Chunks: Read Ahead" title="Direct link to Optimization For Small Chunks: Read Ahead" translate="no">​</a></h2>
<p>Streams tend to have consistent structure: if a stream contains small chunks at one point, it's likely composed mostly of small chunks.
So why not try to read several chunks ahead if a chunk we just read is small?
Dispatching several chunks still requires multiple frames, but we only need to read from the file system once, saving some costly system calls.</p>
<p>The read-ahead limit is 4,096 bytes, so not all small-chunk streams will benefit from this optimization.
Still, this rather simple idea improves the delivery rates dramatically for targeted streams.
Even better, RabbitMQ uses this technique for all protocols, not only the stream protocol but also AMQP.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-results">Performance Results<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#performance-results" class="hash-link" aria-label="Direct link to Performance Results" title="Direct link to Performance Results" translate="no">​</a></h2>
<p>We used a 3-node cluster and a VM to run tests with <a href="https://github.com/rabbitmq/rabbitmq-perf-test/" target="_blank" rel="noopener noreferrer" class="">PerfTest</a> and <a href="https://github.com/rabbitmq/rabbitmq-stream-perf-test/" target="_blank" rel="noopener noreferrer" class="">Stream PerfTest</a>.
All VMs were <code>m7i.4xlarge</code> AWS instances.
We created streams and filled them with 3 million messages, varying the message size and chunk size for each stream.
We then consumed all messages using PerfTest (AMQP 0.9.1) and Stream PerfTest (stream protocol).
We ran tests against RabbitMQ 4.1.4 and 4.2.0-beta.3.</p>
<p>We filled the streams with a tool written for the occasion to have the expected chunk sizes.
Here are the performance tool commands to consume the messages:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># PerfTest</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">java</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-jar</span><span class="token plain"> perf-test.jar </span><span class="token parameter variable" style="color:#36acaa">--producers</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--consumers</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--predeclared</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--qos</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">200</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --stream-consumer-offset first </span><span class="token parameter variable" style="color:#36acaa">--cmessages</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3000000</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--queue</span><span class="token plain"> stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Stream PerfTest</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">java</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-jar</span><span class="token plain"> stream-perf-test.jar </span><span class="token parameter variable" style="color:#36acaa">--producers</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--consumers</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--offset</span><span class="token plain"> first </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --initial-credits </span><span class="token number" style="color:#36acaa">50</span><span class="token plain"> --no-latency </span><span class="token parameter variable" style="color:#36acaa">--cmessages</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3000000</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--streams</span><span class="token plain"> stream</span><br></span></code></pre></div></div>
<p><strong>12-byte messages, AMQP 0.9.1</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/amqp091-12-f7c423b333167859083c67d6d61b0351.svg" width="638" height="354" class="img_ev3q"></p>
<p>Even if a 12-byte message is tiny, we see the read-ahead approach works well: 10 times faster for a stream with 1-message chunks.
Rate is still twice as high with a 384-message-per-chunk stream.</p>
<p><strong>12-byte messages, stream protocol</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/stream-12-713761f8a8c1be9a0801ffda59e63a94.svg" width="646" height="354" class="img_ev3q"></p>
<p>We achieved almost a 10x increase for a 1-message-per-chunk stream with the stream protocol (16,000 vs 134,000 msg/s).
Read-ahead performs better until reaching 128 messages per chunk.</p>
<p>The results for the other message sizes are consistent, we will discuss them at the end.</p>
<p><strong>48-byte Messages, AMQP 0.9.1</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/amqp091-48-1e375d7b74e6d3947d2cd93f23cfd84b.svg" width="538" height="349" class="img_ev3q"></p>
<p><strong>48-byte messages, stream protocol</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/stream-48-a2f6b7c7f442da70cbde302f16792548.svg" width="546" height="349" class="img_ev3q"></p>
<p><strong>256-byte Messages, AMQP 0.9.1</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/amqp091-256-be84943827df9bfb8958201bd024383a.svg" width="437" height="349" class="img_ev3q"></p>
<p><strong>256-byte messages, stream protocol</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/stream-256-570e88c9c9af9d50af38ef91ff48ad7d.svg" width="437" height="349" class="img_ev3q"></p>
<p><strong>512-byte Messages, AMQP 0.9.1</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/amqp091-512-87cee2eca34b6d24e11fb844e6ed9940.svg" width="387" height="349" class="img_ev3q"></p>
<p><strong>512-byte messages, stream protocol</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/stream-512-b5806c1843380fd646bcd31ffa2c1cbb.svg" width="387" height="349" class="img_ev3q"></p>
<p><strong>1024-byte Messages, AMQP 0.9.1</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/amqp091-1024-f449f7f858fde7f091dec21e210d500f.svg" width="331" height="343" class="img_ev3q"></p>
<p><strong>1024-byte messages, stream protocol</strong></p>
<p><img decoding="async" loading="lazy" src="https://www.rabbitmq.com/assets/images/stream-1024-001d2c6631c64815dc5a926713d24bf6.svg" width="337" height="343" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="result-analysis">Result Analysis<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#result-analysis" class="hash-link" aria-label="Direct link to Result Analysis" title="Direct link to Result Analysis" translate="no">​</a></h3>
<p>The consumption rate improves as expected with the stream protocol: it is higher for streams with small chunks but remains the same when a chunk reaches the read-ahead limit (4,096 bytes).
This is particularly noticeable with 1,024-byte messages, where the rate improved for chunk sizes of 1 and 2 (less than the read-ahead limit) but stays roughly the same for chunk sizes of 4 and 6 (reaching or exceeding the limit, so read-ahead does not kick in).</p>
<p>The trend is similar with AMQP 0.9.1, but we still observe improved results after a chunk exceeds the read-ahead limit.
With AMQP 0.9.1 (and other non-stream protocols, like AMQP 1.0), RabbitMQ uses an iterator-like approach to dispatch messages.
This approach was already using a form of read-ahead, but it's now more aggressive and better adapts to the size of chunks.
This explains the good results with AMQP 0.9.1 that we should also get with other non-stream protocols.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="last-details">Last Details<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#last-details" class="hash-link" aria-label="Direct link to Last Details" title="Direct link to Last Details" translate="no">​</a></h2>
<p>The read-ahead optimization is enabled by default but can be disabled globally by setting the <code>stream.read_ahead</code> configuration entry to <code>false</code>.</p>
<p>Large chunks are still dispatched to consumers in an optimized manner: the chunk header is read in memory but the chunk data (the messages) are sent through the socket in a <a href="https://man7.org/linux/man-pages/man2/sendfile.2.html" target="_blank" rel="noopener noreferrer" class="">zero-copy fashion</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://www.rabbitmq.com/blog/2025/09/26/stream-delivery-optimization#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>The read-ahead optimization in RabbitMQ 4.2 proves that sometimes looking ahead pays off—delivering up to 10x better performance for streams with small chunks across all protocols.
Who knew that being a little greedy when reading from disk could make your consumers so much happier?</p>]]></content:encoded>
            <category>Streams</category>
            <category>RabbitMQ 4.2</category>
            <category>performance</category>
        </item>
        <item>
            <title><![CDATA[Broker-Side SQL Filtering with RabbitMQ Streams]]></title>
            <link>https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions</link>
            <guid>https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions</guid>
            <pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.2 introduces SQL filter expressions for streams, enabling powerful broker-side message filtering.]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ 4.2 introduces SQL filter expressions for <a class="" href="https://www.rabbitmq.com/docs/streams">streams</a>, enabling powerful broker-side message filtering.</p>
<p>In our benchmarks, combining SQL filters with Bloom filters achieved filtering rates of more than 4 million messages per second — in highly selective scenarios with high ingress rates.
This means only the messages your consumers actually care about leave the broker, greatly reducing network traffic and client-side processing overhead.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="motivation">Motivation<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation" translate="no">​</a></h2>
<p>High-throughput event streams often deliver large volumes of data to consumers, much of which may not be relevant to them.
In real systems there may be tens of thousands of subjects (event types, tenants, regions, SKUs, etc.), making a dedicated stream per subject impractical or unscalable.</p>
<p>RabbitMQ Streams address this with broker-side <a class="" href="https://www.rabbitmq.com/docs/next/stream-filtering">filtering</a>.</p>
<p><a class="" href="https://www.rabbitmq.com/docs/next/stream-filtering#stage-1-bloom-filter">Bloom filters</a> skip entire chunks that don’t contain values of interest, while <a class="" href="https://www.rabbitmq.com/docs/next/stream-filtering#sql-filter-expressions">SQL Filter Expressions</a> evaluate precise per-message predicates so only matching messages cross the network.
This reduces network traffic, lowers client CPU and memory use, and keeps application code simpler.</p>
<p>Demand for broker-side filtering is longstanding - Kafka users have requested it for years (see <a href="https://issues.apache.org/jira/browse/KAFKA-6020" target="_blank" rel="noopener noreferrer" class="">KAFKA-6020</a>) — but Kafka still lacks this capability.
RabbitMQ’s Bloom + SQL filtering makes selective consumption practical at scale today.</p>
<p>Let’s walk through a hands-on example.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="running-the-sample-app">Running the Sample App<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#running-the-sample-app" class="hash-link" aria-label="Direct link to Running the Sample App" title="Direct link to Running the Sample App" translate="no">​</a></h2>
<p>To run this example in your environment:</p>
<ol>
<li class="">Start RabbitMQ with a single scheduler thread:</li>
</ol>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> rabbitmq </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5672</span><span class="token plain">:5672 </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">ERL_AFLAGS</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"+S 1"</span><span class="token plain"> rabbitmq:4.2.0-beta.3</span><br></span></code></pre></div></div>
<ol start="2">
<li class="">From the root directory of the <a href="https://github.com/ansd/sql-filter-expressions/tree/blog-post" target="_blank" rel="noopener noreferrer" class="">sample application</a>, run:</li>
</ol>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mvn clean compile exec:java</span><br></span></code></pre></div></div>
<p>The sample application uses the <a href="https://github.com/rabbitmq/rabbitmq-amqp-java-client" target="_blank" rel="noopener noreferrer" class="">RabbitMQ AMQP 1.0 Java Client</a>, as SQL filter expressions are a feature of AMQP 1.0.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="publishing-events">Publishing Events<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#publishing-events" class="hash-link" aria-label="Direct link to Publishing Events" title="Direct link to Publishing Events" translate="no">​</a></h2>
<p>Consider a typical e-commerce platform generating a continuous stream of customer events:</p>
<ul>
<li class=""><code>product.search</code></li>
<li class=""><code>product.view</code></li>
<li class=""><code>cart.add</code></li>
<li class=""><code>cart.remove</code></li>
<li class=""><code>order.created</code></li>
<li class="">and many others</li>
</ul>
<p>Our sample application publishes 10 million such events to a stream, with <code>order.created</code> events occurring every 100,000 messages — representing just 0.001% of the total volume.</p>
<p>Each message includes a Bloom filter annotation set to its event type, enabling efficient chunk-level filtering:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">publisher</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">message</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">priority</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priority</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// set the Bloom filter value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">annotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"x-stream-filter-value"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">creationTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">creationTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// set application properties, e.g. region, price, or premium_customer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">property</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"region"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> region</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="defining-your-filter">Defining Your Filter<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#defining-your-filter" class="hash-link" aria-label="Direct link to Defining Your Filter" title="Direct link to Defining Your Filter" translate="no">​</a></h2>
<p>Suppose you only want to process high-value orders that satisfy all of the following:</p>
<ul>
<li class="">Event type is <code>order.created</code></li>
<li class="">Order was created within the last hour</li>
<li class="">Order originates from regions AMER, EMEA, or APJ</li>
<li class="">And at least one of:<!-- -->
<ul>
<li class="">Priority &gt; 4</li>
<li class="">Price ≥ 99.99</li>
<li class="">Premium customer</li>
</ul>
</li>
</ul>
<p>In our demonstration, only 10 messages out of 10 million meet these criteria — a highly selective filter scenario common in real-world applications.</p>
<p>Traditional approaches would require consuming all 10 million messages and filtering client-side, resulting in significant network overhead and wasted resources.</p>
<p>SQL filter expressions solve this elegantly by performing all filtering broker-side:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token class-name">String</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SQL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token string" style="color:#e3116c">"properties.subject = 'order.created' AND "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token string" style="color:#e3116c">"properties.creation_time &gt; UTC() - 3600000 AND "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token string" style="color:#e3116c">"region IN ('AMER', 'EMEA', 'APJ') AND "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token string" style="color:#e3116c">"(header.priority &gt; 4 OR price &gt;= 99.99 OR premium_customer = TRUE)"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>The consumer implementation becomes straightforward:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token class-name">ConsumerBuilder</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">StreamOptions</span><span class="token plain"> builder </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> connection</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">consumerBuilder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">queue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">STREAM_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">offset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">FIRST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">useBloomFilter</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Stage 1: Bloom filter - quickly skip chunks without order.created events</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    builder </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> builder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filterValues</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"order.created"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Consumer</span><span class="token plain"> consumer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> builder</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Stage 2: SQL filter - precise broker-side per-message filtering</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sql</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SQL</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">messageHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> msg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"  [%s] Received: %s\n"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            consumerType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        latch</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">countDown</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">accept</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-results">Performance Results<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#performance-results" class="hash-link" aria-label="Direct link to Performance Results" title="Direct link to Performance Results" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="sql-filtering-only">SQL Filtering Only<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#sql-filtering-only" class="hash-link" aria-label="Direct link to SQL Filtering Only" title="Direct link to SQL Filtering Only" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Received 10 messages in 24.71 seconds using SQL filter only</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Broker-side filtering rate: 404,645 messages/second</span><br></span></code></pre></div></div>
<p>The consumer receives exactly 10 messages that match the criteria.
All filtering occurs on the broker, processing over 400k messages per second while transmitting only the relevant data over the network.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bloom--sql-filtering">Bloom + SQL Filtering<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#bloom--sql-filtering" class="hash-link" aria-label="Direct link to Bloom + SQL Filtering" title="Direct link to Bloom + SQL Filtering" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Received 10 messages in 2.05 seconds using Bloom + SQL filters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Broker-side filtering rate: 4,868,549 messages/second</span><br></span></code></pre></div></div>
<p>By combining both filtering stages, performance improves by an order of magnitude.
The Bloom filter (Stage 1) eliminates entire chunks that don't contain <code>order.created</code> events before they're read from disk, while the SQL filter (Stage 2) applies precise business logic to the remaining messages.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>By combining Bloom filters with SQL filter expressions, RabbitMQ delivers the best of both:
efficient chunk-level filtering at Stage 1 to skip unnecessary disk I/O, CPU, and memory usage, followed by precise message-level filtering at Stage 2 for complex business logic — all on the broker.</p></div></div>
<p>Note that actual Bloom filtering performance depends on the number of messages per chunk, which varies with message ingress rates.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="learn-more">Learn More<a href="https://www.rabbitmq.com/blog/2025/09/23/sql-filter-expressions#learn-more" class="hash-link" aria-label="Direct link to Learn More" title="Direct link to Learn More" translate="no">​</a></h2>
<p>Check out our new <a class="" href="https://www.rabbitmq.com/docs/next/stream-filtering">Stream Filtering</a> guide for best practices, examples, and configuration tips.</p>]]></content:encoded>
            <category>AMQP 1.0</category>
            <category>Streams</category>
            <category>RabbitMQ 4.2</category>
            <category>New Features</category>
        </item>
        <item>
            <title><![CDATA[The Roadmap for Making Khepri the Default Metadata Store in RabbitMQ]]></title>
            <link>https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default</link>
            <guid>https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default</guid>
            <pubDate>Mon, 01 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Khepri, the new Raft-based RabbitMQ metadata store, became fully supported with RabbitMQ 4.0.]]></description>
            <content:encoded><![CDATA[<p>Khepri, the new Raft-based RabbitMQ <a class="" href="https://www.rabbitmq.com/docs/metadata-store">metadata store</a>, became fully supported with RabbitMQ 4.0.
Starting with the next release series, RabbitMQ 4.2, we consider Khepri to be mature enough to become the default metadata store,
especially given its substantial data safety and recovery improvements over Mnesia.</p>
<p>We have performed a number of benchmarks, showing significant performance improvements in many metadata operations.
A comparison table can be found below.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="khepri-feature-flag-now-stable">Khepri Feature Flag now stable<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#khepri-feature-flag-now-stable" class="hash-link" aria-label="Direct link to Khepri Feature Flag now stable" title="Direct link to Khepri Feature Flag now stable" translate="no">​</a></h2>
<p>The <code>khepri_db</code> feature flag has now been upgraded to <code>Stable</code>, meaning it will now be enabled when running the command <code>rabbitmqctl enable_feature_flag all</code>,
which should be done after every successful version upgrade.</p>
<p>Starting with version 4.2, all RabbitMQ clusters will be strongly recommended to adopt Khepri by enabling the <code>khepri_db</code> feature flag. This feature flag will
<strong>likely become mandatory</strong> for upgrading from 4.2 onwards.</p>
<p>While the final decision depends on the community feedback, we expect that starting with RabbitMQ 4.3,
the <code>khepri_db</code> feature flag will <a class="" href="https://www.rabbitmq.com/docs/feature-flags#graduation">graduate</a> to be <code>Required</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="feature-flag-subsystem">Feature Flag Subsystem<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#feature-flag-subsystem" class="hash-link" aria-label="Direct link to Feature Flag Subsystem" title="Direct link to Feature Flag Subsystem" translate="no">​</a></h3>
<p>The RabbitMQ <a class="" href="https://www.rabbitmq.com/docs/feature-flags">feature flag subsystem</a> was recently improved by introducing a new category of feature flags known as <code>Soft Required</code>.
If a feature flag is <code>Soft Required</code> starting from version <code>N</code>, it is automatically enabled once all RabbitMQ nodes are upgraded to version <code>N</code> of RabbitMQ.
This is a change from the previous behavior of <code>Required</code>, where a feature flag that became required in version <code>N</code> of RabbitMQ must be enabled before upgrading to version <code>N</code>.</p>
<p>It remains best practice to enable feature flags as soon as they become <code>Stable</code>, generally immediately after a successful upgrade by running the command <code>rabbitmqctl enable_feature_flag all</code>.
Nonetheless, we view the introduction of <code>Soft Required</code> feature flags as an improvement in user experience,
as any required feature flags not already enabled will be automatically enabled when required.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="khepri-performance-improvements">Khepri Performance Improvements<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#khepri-performance-improvements" class="hash-link" aria-label="Direct link to Khepri Performance Improvements" title="Direct link to Khepri Performance Improvements" translate="no">​</a></h2>
<p>The benchmarks below were performed on a 3 node cluster running on Kubernetes</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1000-queues-each-with-100-bindings">1000 queues, each with 100 bindings<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#1000-queues-each-with-100-bindings" class="hash-link" aria-label="Direct link to 1000 queues, each with 100 bindings" title="Direct link to 1000 queues, each with 100 bindings" translate="no">​</a></h3>
<table><thead><tr><th>benchmark</th><th>mnesia</th><th>khepri</th></tr></thead><tbody><tr><td>import</td><td>446 s</td><td>51 s</td></tr><tr><td>re-import</td><td>16 s</td><td>46 s</td></tr><tr><td>stop_app</td><td>1.6 s</td><td>1.7 s</td></tr><tr><td>start_app</td><td>22 s</td><td>4.3 s</td></tr><tr><td>rolling cluster restart</td><td>108 s</td><td>67 s</td></tr><tr><td>mnesia to khepri migration</td><td>12.7 s</td><td></td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1000-vhosts">1000 Vhosts<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#1000-vhosts" class="hash-link" aria-label="Direct link to 1000 Vhosts" title="Direct link to 1000 Vhosts" translate="no">​</a></h3>
<table><thead><tr><th>benchmark</th><th>mnesia</th><th>khepri</th></tr></thead><tbody><tr><td>import</td><td>284 s</td><td>21 s</td></tr><tr><td>re-import</td><td>2.2 s</td><td>2.2 s</td></tr><tr><td>stop_app</td><td>2.6 s</td><td>2.4 s</td></tr><tr><td>start_app</td><td>419 s</td><td>16 s</td></tr><tr><td>rolling cluster restart</td><td>1447 s</td><td>106 s</td></tr><tr><td>mnesia to khepri migration</td><td>5.5 s</td><td></td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="100000-classic-queues">100,000 Classic Queues<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#100000-classic-queues" class="hash-link" aria-label="Direct link to 100,000 Classic Queues" title="Direct link to 100,000 Classic Queues" translate="no">​</a></h3>
<table><thead><tr><th>benchmark</th><th>mnesia</th><th>khepri</th></tr></thead><tbody><tr><td>import</td><td>76 s</td><td>76 s</td></tr><tr><td>re-import</td><td>5.4 s</td><td>5.3 s</td></tr><tr><td>stop_app</td><td>13 s</td><td>6 s</td></tr><tr><td>start_app</td><td>26 s</td><td>40 s</td></tr><tr><td>rolling cluster restart</td><td>185 s</td><td>307 s</td></tr><tr><td>mnesia to khepri migration</td><td>9.7 s</td><td></td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="10000-quorum-queues">10,000 Quorum Queues<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#10000-quorum-queues" class="hash-link" aria-label="Direct link to 10,000 Quorum Queues" title="Direct link to 10,000 Quorum Queues" translate="no">​</a></h3>
<table><thead><tr><th>benchmark</th><th>mnesia</th><th>khepri</th></tr></thead><tbody><tr><td>import</td><td>49 s</td><td>46 s</td></tr><tr><td>re-import</td><td>1.9 s</td><td>1.8 s</td></tr><tr><td>stop_app</td><td>1.9 s</td><td>1.7 s</td></tr><tr><td>start_app</td><td>44 s</td><td>44 s</td></tr><tr><td>rolling cluster restart</td><td>285 s</td><td>267 s</td></tr><tr><td>mnesia to khepri migration</td><td>4.7 s</td><td></td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1000-streams">1,000 Streams<a href="https://www.rabbitmq.com/blog/2025/09/01/6-khepri-default#1000-streams" class="hash-link" aria-label="Direct link to 1,000 Streams" title="Direct link to 1,000 Streams" translate="no">​</a></h3>
<table><thead><tr><th>benchmark</th><th>mnesia</th><th>khepri</th></tr></thead><tbody><tr><td>import</td><td>3.5 s</td><td>1.2 s</td></tr><tr><td>re-import</td><td>1.6 s</td><td>1.2 s</td></tr><tr><td>stop_app</td><td>1.9 s</td><td>1.2 s</td></tr><tr><td>start_app</td><td>2.5 s</td><td>2.3 s</td></tr><tr><td>rolling cluster restart</td><td>56 s</td><td>55 s</td></tr><tr><td>mnesia to khepri migration</td><td>5 s</td><td></td></tr></tbody></table>]]></content:encoded>
            <category>khepri</category>
        </item>
        <item>
            <title><![CDATA[Migrating from Classic Mirrored Queues to Quorum Queues in 2025]]></title>
            <link>https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way</link>
            <guid>https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way</guid>
            <pubDate>Tue, 29 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4 has been out for some time by now, and we have covered some of the goodies it comes with,]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ 4 has been out for some time by now, and we have covered some of the goodies it comes with,
compared to its predecesor, RabbitMQ 3.13. Some examples are
<a class="" href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements">improved performance</a>,
<a class="" href="https://www.rabbitmq.com/blog/2024/08/05/native-amqp">Native AMQP 1.0</a>, new
<a class="" href="https://www.rabbitmq.com/blog/2024/08/28/quorum-queues-in-4.0">Quorum Queue features</a>, bringing
closer feature parity with Classic Queues.</p>
<p>It's been a while since we wrote about
<a class="" href="https://www.rabbitmq.com/blog/2023/03/02/quorum-queues-migration">how to migrate</a> from Classic
Mirrored Queues (CMQ) to Quorum Queues (QQ). In case you already don't know, CMQs are deprecated
since RabbitMQ 3.9, and were removed in RabbitMQ 4.0. Today we are going to cover Quorum Queues in
more detailed, comparing them to CMQs, and high level migration stategies to abandon CMQs for good,
in favour of QQs, or a combination of QQ and Classic Queues (CQ). Note that CQs are still well
supported, it's their mirroring feature what was deprecated and removed.</p>
<h1>Why Quorum Queues?</h1>
<p>Mirrored Classic Queues, a.k.a. Classic Mirrored Queues, a.k.a. CMQs, were introduced to add in-cluster data replication to
classic queues (CQs). The CQs were originally designed as a non-replicated queue type back in 2006,
during the first year of RabbitMQ development.</p>
<p>Then around 2009, the mirroring feature added the ability to replicate
data to other nodes. The algorithm to "mirror" data was homegrown, and it was not very resilient to
network partitions. To make matters worse, the behaviour in failure scenarios of CMQs was
unpredictable in some cases, and generally quite hard to reason about. There were even cases where
<a href="https://jack-vanlightly.com/blog/2018/9/10/how-to-lose-messages-on-a-rabbitmq-cluster" target="_blank" rel="noopener noreferrer" class="">CMQs could lose messages</a>.</p>
<p>To address all these issues, and to supercharge RabbitMQ with a reliable, safe and replicated queue
type, Quorum Queues were designed and incorporated to RabbitMQ.</p>
<p><a class="" href="https://www.rabbitmq.com/docs/quorum-queues">Quorum Queues</a> are replicated queue type from the ground up, based on <a href="https://raft.github.io/" target="_blank" rel="noopener noreferrer" class="">Raft consensus algorithm</a>.
Quorum Queues are designed with data safety as top priority.  All QQs have a leader and some followers; locagically, leader and followers are
distributed among RabbitMQ nodes. When a QQ leader receives a message, it records this operation in
a write-ahead log (WAL), then stores the message on disk on a local Raft log and in parallel issues replication commands
to the followers, and awaits for a confirmation from a majority before sending a confirmation back to the client.</p>
<p>One key difference with CMQs is that the replication part is done in parallel, while CMQs use a chain
replication algorithm. Another important difference between the two: <a class="" href="https://www.rabbitmq.com/docs/quorum-queues#motivation">quorum queues pass a stricter version of the Jepsen test</a>, while CMQs fail to pass even a less
demanding original version.</p>
<p>In the event of a leader failure, the up-to-date followers start a voting process, and elect a new
QQ leader. The resulting leader will resume operations on the queue. You can learn more details
about <a href="https://raft.github.io/" target="_blank" rel="noopener noreferrer" class="">Raft consensus algorithm</a> in GitHub.</p>
<p>With those characteristics, QQs address the main issues of CMQs: data safety and
predictability of failure scenarios. On top of that, quorum queues offer <a class="" href="https://www.rabbitmq.com/docs/quorum-queues#feature-comparison">nearly a feature parity</a> and better throughput for many workloads.</p>
<p>However, QQs are not a good fit for certain use cases present
in messaging systems. For example: temporary queues used in e.g. RPC (request-reply) communication.</p>
<p>It doesn't make sense to use a quroum queue for very short lived transient data, since data safety
will not be a priority for such use cases. For example, if your applications use a
fire-and-forget approach to publish messages, and/or your consumer applications don't use manual
acknowledgement. For such use cases, Classic Queues <strong>without mirroring</strong> are an excelent fit.</p>
<h1>Migration from CMQs to QQs</h1>
<p>Given the different nature of both queue types, including at the storage level, it is not possible to
turn an existing classic queue into a quorum queue "in place".</p>
<p>However, a <a class="" href="https://www.rabbitmq.com/docs/blue-green-upgrade">Blue-Green Deployment</a> can be used for
migrating. This is a strategy where applications are migrated from an existing cluster with mirrored classic queues,
called the "blue" cluster, to a new cluster, the "green" one, which will use quorum queues for all
classic queues that were replicated in the blue cluster.</p>
<p>RabbitMQ has tooling to facilitate the migration. <a class="" href="https://www.rabbitmq.com/docs/management-cli">`rabbitmqadmin v2</a>,
an <a class="" href="https://www.rabbitmq.com/docs/management#http-api">HTTP API</a>-based CLI tool <a href="https://github.com/rabbitmq/rabbitmqadmin-ng/" target="_blank" rel="noopener noreferrer" class="">built by the RabbitMQ Core Team at Broadcom</a>,
supports a number of commands that simplify the migration.</p>
<p>Before jumping into the details, let's take a look at how an existing RabbitMQ <code>3.13.x</code> cluster that
uses mirrored classic queues can be migrated to a new <code>4.1.x</code> cluster that will use quorum queues
for all replicated queues.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="high-level-migration-plan">High Level Migration Plan<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#high-level-migration-plan" class="hash-link" aria-label="Direct link to High Level Migration Plan" title="Direct link to High Level Migration Plan" translate="no">​</a></h2>
<p>The Blue-Green upgrade strategy has some requirements that must be met prior to the upgrade:</p>
<ul>
<li class=""><a class="" href="https://www.rabbitmq.com/docs/federation">RabbitMQ Queue Federation</a> must be enabled</li>
<li class="">The Blue (original) cluster must be reachable from the Green (new) one for queue federation to work</li>
<li class="">The Green (new) RabbitMQ version must run a <code>4.x</code> version, ideally latest version available</li>
<li class="">All stable <a class="" href="https://www.rabbitmq.com/docs/feature-flags">feature flags</a> must be enabled in Green (new) cluster</li>
</ul>
<p>Once the prerequisites are met, the migration plan consists of the following steps:</p>
<ol>
<li class="">Export the definitions from the Blue cluster using <code>rabbitmqadmin</code> v2 and apply a few transformations to
make sure that the definitions do not include any keys that the new cluster does not support (namely, the CMQ mirroring policies)</li>
<li class="">Import definitions into the Green cluster</li>
<li class="">Configure <a class="" href="https://www.rabbitmq.com/docs/federated-queues">queue federation</a> between the two clusters</li>
<li class="">Migrate consumers to the Green cluster</li>
<li class="">Migrate producers to the Green cluster</li>
<li class=""><a class="" href="https://www.rabbitmq.com/docs/monitoring">Monitor</a> the state of the Green cluster</li>
<li class="">Shutdown the original cluster</li>
<li class="">Remove a number of temporary migration policies from Green</li>
</ol>
<p>Now, let's dive into the details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="considerations-for-applications">Considerations for Applications<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#considerations-for-applications" class="hash-link" aria-label="Direct link to Considerations for Applications" title="Direct link to Considerations for Applications" translate="no">​</a></h2>
<p>Quorum Queues support all features of durable mirrored classic queues. That means that most applications
can be moved to the new cluster without any changes. For the small percentage of applications that explicitly
specifies a queue type, a <a class="" href="https://www.rabbitmq.com/docs/quorum-queues#relaxed-property-equivalence">special <code>rabbitmq.conf</code> setting</a>
can be used to relax a key queue property equivalence check performed by RabbitMQ nodes when a client
tries to declare a queue.</p>
<p>The <a class="" href="https://www.rabbitmq.com/docs/quorum-queues#feature-comparison">feature comparison matrix</a> covers how Quorum
Queues are different from Classic Queues.</p>
<p>This is a good moment to reconsider whether certain apps need to use replicated queues at all. For example, an
application that creates and binds a temporary queue to a fanout exchange, process information for
some time and deletes its queue after disconnection, will not benefit from what a replicated queue type —
quorum queues — have to offer, because the queue is very short lived, specific to a particular client,
and the app is capable of re-declaring its topology.</p>
<p>If some queues do not need to be replicated, remove the classic queue mirroring-related keys from
their policies before proceeding. The keys are</p>
<ul>
<li class=""><code>"ha-mode"</code></li>
<li class=""><code>"ha-params"</code></li>
<li class=""><code>"ha-promote-on-shutdown"</code></li>
<li class=""><code>"ha-promote-on-failure"</code></li>
<li class=""><code>"ha-sync-mode"</code></li>
<li class=""><code>"ha-sync-batch-size"</code></li>
</ul>
<p>Such non-replicated classic queues will be migrated as classic queues
to the Green cluster, avoiding the use of quorum queues where they are not necessary.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="detailed-migration-plan">Detailed Migration Plan<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#detailed-migration-plan" class="hash-link" aria-label="Direct link to Detailed Migration Plan" title="Direct link to Detailed Migration Plan" translate="no">​</a></h2>
<p>This plan has been tested with RabbitMQ Blue 3.13.7 and RabbitMQ Green 4.1.2. Both TLS, mTLS and
plain TCP has been tested. Both the CLI <code>rabbitmqadmin</code> v2 and RabbitMQ work without issues in all the
tested setups.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="export-definitions-from-the-blue-cluster">Export Definitions From the Blue Cluster<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#export-definitions-from-the-blue-cluster" class="hash-link" aria-label="Direct link to Export Definitions From the Blue Cluster" title="Direct link to Export Definitions From the Blue Cluster" translate="no">​</a></h3>
<p>In this step, we will backup all rabbitmq objects, excluding messages, to a JSON file. All
usernames, vhosts, queues, permissions, bindings, policies, parameters, exchanges, everything, will
be exported to a JSON file. It is possible to apply transformations to exclude certain data. This
transformations feature will greatly help with the CMQ to QQ migration.</p>
<p>The following command exports a definitions file of RabbitMQ and transforms the result by removing the deprecated CMQ policy
keys and <a class="" href="https://www.rabbitmq.com/docs/queues#optional-arguments">optional queue arguments</a>,
replacing previously mirrored classic queues with quorum queues.</p>
<p>Any queue that had a mirroring <a class="" href="https://www.rabbitmq.com/docs/policies">policy</a> applied to it will be automatically
transformed into a Quorum Queue in the definitions (backup) file. If as a result of this
transformations, a policy becomes empty (beecause it only had CMQ keys), it will also be deleted,
because it is not possible to import empty policies in RabbitMQ.</p>
<p>RabbitMQ definitions are shared among all cluster nodes, therefore, it is only necessary to run this
command in one node.</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Export definitions from the original cluster into a file and applies two transformations</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># to remove all traces of classic mirrored queues</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> blue definitions </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--file</span><span class="token plain"> blue.json </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> prepare_for_quorum_queue_migration,drop_empty_policies</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="import-definitions">Import definitions<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#import-definitions" class="hash-link" aria-label="Direct link to Import definitions" title="Direct link to Import definitions" translate="no">​</a></h3>
<p>In this step, we will "restore" the definitions file from the previous step (with the CMQs
transformed into QQ) into the new "green" cluster. This command does not allow for much
configurability, it's a very straightforward step:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Import definitions into the new (Green) cluster</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green definitions </span><span class="token function" style="color:#d73a49">import</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--file</span><span class="token plain"> ./blue.json</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="configure-a-federation-upstream-in-green">Configure a Federation Upstream in Green<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#configure-a-federation-upstream-in-green" class="hash-link" aria-label="Direct link to Configure a Federation Upstream in Green" title="Direct link to Configure a Federation Upstream in Green" translate="no">​</a></h3>
<p>In this step, we will configure <a class="" href="https://www.rabbitmq.com/docs/federated-queues">queue federation</a>. These steps are critically important because it's the queue
federation links that will be transferring any existing messages from the original cluster to the new ones,
which allows applications to be moved to the new cluster at a later stage.</p>
<p>Take some time to read through and prepare the commands in advance.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-federation-upstreams">Create federation upstreams<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#create-federation-upstreams" class="hash-link" aria-label="Direct link to Create federation upstreams" title="Direct link to Create federation upstreams" translate="no">​</a></h4>
<p><strong>For each vhost</strong>, create a federation upstream in <strong>Green</strong>:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green federation declare_upstream_for_queues </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> cmq-qq-migration </span><span class="token parameter variable" style="color:#36acaa">--uri</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'amqp://&lt;federation-user&gt;:&lt;federation-password&gt;@blue.rabbit'</span><br></span></code></pre></div></div>
<p>Where <code>&lt;federation-user&gt;</code> is an <strong>existing user</strong> in <strong>Blue</strong> RabbitMQ. It is advisable to create a
dedicated user for federation.</p>
<p>Where <code>&lt;federation-password&gt;</code> is the federation user password used to authenticate in <strong>Blue</strong>
RabbitMQ.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-override-policies">Create Override Policies<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#create-override-policies" class="hash-link" aria-label="Direct link to Create Override Policies" title="Direct link to Create Override Policies" translate="no">​</a></h4>
<p>This step creates <a class="" href="https://www.rabbitmq.com/docs/policies#override">"override" policies</a> to enable queue federation for all queues
that are already matched by a policy. Note that the override policy is a <code>rabbitmqadmin</code> v2 concept, not a
RabbitMQ HTTP API, so this operation can be performed on a <code>3.13.x</code> node.</p>
<p>In this step, we are configuring RabbitMQ to use <a class="" href="https://www.rabbitmq.com/docs/federated-queues">federated queues</a>. Federated queues
transfer messages from the upstream cluster, when <strong>local</strong> consumers request messages <strong>and</strong> local
queues are empty. This will allow you to move your consumer applications to Green without disruption
to your operations.</p>
<p>For each policy, create a policy override to utilise the federation upstream:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies list</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ┌──────┬─────────┬───────────────────────┬──────────┬──────────┬──────────────────┐</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ name │ vhost   │ pattern               │ apply_to │ priority │ definition       │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────┼─────────┼───────────────────────┼──────────┼──────────┼──────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ ha   │ finance │ (?:^po$)|(?:.*\.dlx$) │ all      │ 0        │ max-length: 100  │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │      │         │                       │          │          │ queue-version: 2 │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │      │         │                       │          │          │                  │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; └──────┴─────────┴───────────────────────┴──────────┴──────────┴──────────────────┘</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies declare_override </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> ha </span><span class="token parameter variable" style="color:#36acaa">--definition</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'{"federation-upstream": "cmq-qq-migration"}'</span><br></span></code></pre></div></div>
<p>Next, create a <a class="" href="https://www.rabbitmq.com/docs/policies#blanket">blanket/catch-all policy</a> for any queues not matched by an existing policy:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies declare_blanket </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> cmq-qq-migration_blanket --apply-to queues </span><span class="token parameter variable" style="color:#36acaa">--definition</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'{"federation-upstream": "cmq-qq-migration"}'</span><br></span></code></pre></div></div>
<p>This will ensure that all queues are federated between the Blue and Green clusters.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="verify-that-federation-is-functional">Verify That Federation is Functional<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#verify-that-federation-is-functional" class="hash-link" aria-label="Direct link to Verify That Federation is Functional" title="Direct link to Verify That Federation is Functional" translate="no">​</a></h4>
<p>Once the policies are created, the federation plugin in the Green cluster will create links (connections)
to the upstream (Blue). The presence of links ensures that federated queues are ready to move messages from the upstream (Blue)
into the Green cluster when the consuming applications are migrated from Blue to Green.</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green federation list_all_links</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ┌──────────────┬─────────┬──────────┬─────────────────────┬─────────┬───────┬──────────────────┬──────────────────────────────────┐</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ node         │ vhost   │ id       │ uri                 │ status  │ type  │ upstream         │ consumer_tag                     │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────┼─────────┼──────────┼─────────────────────┼─────────┼───────┼──────────────────┼──────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ rabbit@green │ finance │ 8f0f0d8a │ amqps://blue.rabbit │ running │ queue │ cmq-qq-migration │ federation-link-cmq-qq-migration │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────┼─────────┼──────────┼─────────────────────┼─────────┼───────┼──────────────────┼──────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ rabbit@green │ finance │ 01efa5b5 │ amqps://blue.rabbit │ running │ queue │ cmq-qq-migration │ federation-link-cmq-qq-migration │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────┼─────────┼──────────┼─────────────────────┼─────────┼───────┼──────────────────┼──────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ rabbit@green │ finance │ 950faf11 │ amqps://blue.rabbit │ running │ queue │ cmq-qq-migration │ federation-link-cmq-qq-migration │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; └──────────────┴─────────┴──────────┴─────────────────────┴─────────┴───────┴──────────────────┴──────────────────────────────────┘</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="prepare-to-move-consumers">Prepare to Move Consumers<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#prepare-to-move-consumers" class="hash-link" aria-label="Direct link to Prepare to Move Consumers" title="Direct link to Prepare to Move Consumers" translate="no">​</a></h4>
<p>Both RabbitMQ clusters (Blue and Green) are ready to support a migration. The first step of the
app migration is moving consumer applications to the new RabbitMQ cluster (Green).</p>
<p>How the applications are deployed to the Green cluster depends entirely on how you deploy and run
RabbitMQ and the applications. There is no urgency or rush to complete
this step. Ensure that your consumer applications are working as expected before moving to the next
step.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="prepare-to-move-producers">Prepare to Move Producers<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#prepare-to-move-producers" class="hash-link" aria-label="Direct link to Prepare to Move Producers" title="Direct link to Prepare to Move Producers" translate="no">​</a></h4>
<p>This is the last step to complete the migration! Moving the producers consists of stopping the
producer apps, letting the consumers drain the queues in Blue via queue federation, and starting the
producer apps in Green.</p>
<p>There is a special scenario if you can't afford to have your producer apps stopped until the
consumers drain your queues. This can be the case if your usage consists of very long backlog queues
and slow consumers. In this special case, in addition to setting up queue fedration, consider declaring
one or more <a class="" href="https://www.rabbitmq.com/docs/shovel">shovels</a> for moving messages from Blue to Green,
before redeploying producer apps into the Green cluster.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="clean-up-after-migrating">Clean Up After Migrating<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#clean-up-after-migrating" class="hash-link" aria-label="Direct link to Clean Up After Migrating" title="Direct link to Clean Up After Migrating" translate="no">​</a></h3>
<p>After confirming that the migration completed successfully and that your apps are working without
issues, proceed to cleanup the policies declared for the needs of the migration, as well as
the federation upstream in the Green cluster.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="delete-temporary-policies">Delete Temporary Policies<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#delete-temporary-policies" class="hash-link" aria-label="Direct link to Delete Temporary Policies" title="Direct link to Delete Temporary Policies" translate="no">​</a></h4>
<p>Override policies created earlier in the process will all be prefixed with <code>override.</code>. In this guide, the name of the
blanket, catch-all policy is <code>cmq-qq-migration_blanket</code>:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies list</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ┌──────────────────────────┬─────────┬───────────────────────┬──────────┬──────────┬─────────────────────────────────────────┐</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ name                     │ vhost   │ pattern               │ apply_to │ priority │ definition                              │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────────────────┼─────────┼───────────────────────┼──────────┼──────────┼─────────────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ cmq-qq-migration_blanket │ finance │ .*                    │ queues   │ -21      │ federation-upstream: "cmq-qq-migration" │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │                                         │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────────────────┼─────────┼───────────────────────┼──────────┼──────────┼─────────────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ ha                       │ finance │ (?:^po$)|(?:.*\.dlx$) │ all      │ 0        │ max-length: 100                         │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │ queue-version: 2                        │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │                                         │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; ├──────────────────────────┼─────────┼───────────────────────┼──────────┼──────────┼─────────────────────────────────────────┤</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │ overrides.ha             │ finance │ (?:^po$)|(?:.*\.dlx$) │ all      │ 100      │ federation-upstream: "cmq-qq-migration" │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │ max-length: 100                         │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │ queue-version: 2                        │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; │                          │         │                       │          │          │                                         │</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># =&gt; └──────────────────────────┴─────────┴───────────────────────┴──────────┴──────────┴─────────────────────────────────────────┘</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies delete </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> cmq-qq-migration_blanket</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green policies delete </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> overrides.ha</span><br></span></code></pre></div></div>
<p>Next, delete the federation upstream that was used for migrating messages:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin </span><span class="token parameter variable" style="color:#36acaa">--host</span><span class="token plain"> green federation delete_upstream </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> cmq-qq-migration</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="testing-the-migration-in-a-development-environment">Testing the Migration in a Development Environment<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#testing-the-migration-in-a-development-environment" class="hash-link" aria-label="Direct link to Testing the Migration in a Development Environment" title="Direct link to Testing the Migration in a Development Environment" translate="no">​</a></h2>
<p>This migration can seem daunting at first. Team RabbitMQ has done extensive testing of different
scenarios and different queue feature combination, however, nothing would give more confidence than
trying this out yourselves in your own environment!</p>
<p>For that reason, it is highly recommended to test
all the migration commands and plan in a development or staging environment. Sometimes it is challenging to make
your own application simulate load as in production. For such cases,
<a href="https://perftest.rabbitmq.com/" target="_blank" rel="noopener noreferrer" class="">RabbitMQ Perf Test</a> is a great alternative to simulate workloads
and test specific RabbitMQ features.</p>
<p>For example, to simulate one producer publishing to exchange <code>inc</code> at a rate of 30 msg/s with
routing key <code>bills</code>, you could use the following perf-test command:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">java -jar perf-test.jar \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    -y 0 -x 1 -c 10 -p -qq \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --rate 30 -e inc \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --routing-key 'bills' \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --uri "amqp://myuser:mypass@blue.rabbit.example.com"</span><br></span></code></pre></div></div>
<p>All perf-test options are documented in
<a href="https://perftest.rabbitmq.com/#basic-usage" target="_blank" rel="noopener noreferrer" class="">Perf Test documentation</a> and in its help command:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">java -jar perf-test.jar --help</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="post-migration-checklist">Post-Migration Checklist<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#post-migration-checklist" class="hash-link" aria-label="Direct link to Post-Migration Checklist" title="Direct link to Post-Migration Checklist" translate="no">​</a></h2>
<p>After completing the migration, the following list can help to double check the success of the
migration. Feel free to add any additional items that make sense in your environment.</p>
<ul>
<li class="">All consumer apps are connected to Green (new) RabbitMQ cluster</li>
<li class="">All producer applications are connected to Green (new) RabbitMQ cluster</li>
<li class="">Temporary policies are not present</li>
<li class="">Federation upstream is not present</li>
<li class="">RabbitMQ does not have any <a class="" href="https://www.rabbitmq.com/docs/alarms">alarm in effect</a></li>
<li class="">All <a class="" href="https://www.rabbitmq.com/docs/monitoring">metrics</a> are within their typical ranges</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-pitfalls">Migration pitfalls<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#migration-pitfalls" class="hash-link" aria-label="Direct link to Migration pitfalls" title="Direct link to Migration pitfalls" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tls">TLS<a href="https://www.rabbitmq.com/blog/2025/07/29/latest-benefits-of-rmq-and-migrating-to-qq-along-the-way#tls" class="hash-link" aria-label="Direct link to TLS" title="Direct link to TLS" translate="no">​</a></h3>
<p><code>rabbitmqadmin</code> v2 supports TLS-enabled connections. However, its requires the <a class="" href="https://www.rabbitmq.com/docs/ssl#peer-verification">trusted CAs</a> to be part of the system trusted CAs.</p>
<p>How to add a trusted CA to your system keychain varies from one operating system to another. The
following links are not a complete reference, but convenience for most common systems:</p>
<ul>
<li class=""><a href="https://support.apple.com/en-gb/guide/keychain-access/kyca2431/mac" target="_blank" rel="noopener noreferrer" class="">MacOS: Add certificates to keychain</a></li>
<li class=""><a href="https://docs.fedoraproject.org/en-US/quick-docs/using-shared-system-certificates/" target="_blank" rel="noopener noreferrer" class="">Fedora: Using Shared System Certificates</a></li>
<li class=""><a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/securing_networks/using-shared-system-certificates_securing-networks" target="_blank" rel="noopener noreferrer" class="">RHEL 9: Using shared system certificates</a></li>
<li class=""><a href="https://documentation.ubuntu.com/server/how-to/security/install-a-root-ca-certificate-in-the-trust-store/" target="_blank" rel="noopener noreferrer" class="">Ubuntu: Install a root CA certificate in the trust store</a></li>
</ul>
<p>Once the CAs are added to the trusted certificate list at the OS level, their bundle file in the
PEM format can be used together with <code>rabbitmqadmin</code>. For example:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin --use-tls --tls-ca-cert-file /path/to/your/chained_ca_certificate.pem queues list</span><br></span></code></pre></div></div>
<p>If you have RabbitMQ configured to use mutual <a class="" href="https://www.rabbitmq.com/docs/ssl#peer-verification">peer verification</a> (<strong>mTLS</strong>),
<code>rabbitmqadmin</code> will also need to be provided with a client certificate and key pair.</p>
<p>For example:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rabbitmqadmin --use-tls --tls-ca-cert-file /path/to/your/chained_ca_certificate.pem </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --tls-cert-file /path/to/your/client_certificate.pem </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --tls-key-file /path/to/your/client_key.pem </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    queues list</span><br></span></code></pre></div></div>
<p>Alternatively, since adding all TLS options to each command can be cumbersome, it is possible to
configure all TLS options, hostname, port and credentials in a <code>rabbitmqadmin</code> configuration file. The configuration
file for <code>rabbitmqadmin</code> is TOML format, and it accepts some options, in addition to a "node" alias.
For example:</p>
<div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[blue]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">hostname = "blue.rabbit"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">tls = true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ca_certificate_bundle_path = "/path/to/your/chained_ca_certificate.pem"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client_certificate_file_path = "/path/to/your/client_certificate.pem"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client_private_key_file_path = "/path/to/your/client_key.pem"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">port = 32795</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[green]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">hostname = "green.rabbit"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">port = 32811</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">tls = true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ca_certificate_bundle_path = "/path/to/your/chained_ca_certificate.pem"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client_certificate_file_path = "/path/to/your/client_certificate.pem"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client_private_key_file_path = "/path/to/your/client_key.pem"</span><br></span></code></pre></div></div>
<p>Use the above configuration with the <code>--config</code> and <code>--node</code>. For example
<code>rabbitmqadmin --config rabbitmqadmin.toml --node blue queues list</code>.</p>
<h1>Conclusion</h1>
<p>Quorum Queues (QQ) are the go-to queue type for data safety in RabbitMQ. They provide predictable
failover behaviour and
<a class="" href="https://www.rabbitmq.com/blog/2022/05/16/rabbitmq-3.10-performance-improvements">higher throughput than Classic Mirrored Queues</a>
(CMQ). Quorum Queues keep receiving updates, performance improvements and bug fixes, whilst Classic
Mirrored Queues are in life support in 3.13 and completely removed in RabbitMQ 4. Classic Queues
(without mirroring) are still a valid and supported queuee type. Classic Queues are still a good fit
for certain uses cases, for example: RPC pattern. Or any use case that does not require high
availability.</p>
<p>With the new generation of <code>rabbitmqadmin</code>, it is now easier than every to migrate from mirrored classic queues to quorum queues,
and at the same time upgrade to the latest <a class="" href="https://www.rabbitmq.com/release-information">supported RabbitMQ release series</a>.</p>]]></content:encoded>
            <category>Classic Queues</category>
            <category>Quorum Queues</category>
            <category>RabbitMQ 4.1</category>
            <category>Upgrade</category>
        </item>
        <item>
            <title><![CDATA[Team RabbitMQ's Debian (apt) Repositories are Moving]]></title>
            <link>https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving</link>
            <guid>https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving</guid>
            <pubDate>Wed, 16 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Attention Debian and Ubuntu users: our apt repositories are moving..]]></description>
            <content:encoded><![CDATA[<p>Attention Debian and Ubuntu users: <a class="" href="https://www.rabbitmq.com/docs/install-debian#apt-quick-start">our apt repositories are moving</a>..</p>
<p>The existing repos, <code>ppa1.rabbitmq.com</code> and <code>ppa2.rabbitmq.com</code>,
will remain in operation until Nov 1, 2025 but not receive any new updates.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="our-debian-apt-repositories-are-moving">Our Debian (Apt) Repositories are Moving<a href="https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving#our-debian-apt-repositories-are-moving" class="hash-link" aria-label="Direct link to Our Debian (Apt) Repositories are Moving" title="Direct link to Our Debian (Apt) Repositories are Moving" translate="no">​</a></h2>
<p>Our Debian (apt) repositories are moving from <code>ppa*.rabbitmq.com</code> to <code>deb*.rabbitmq.com</code>. The new
repositories are live and <a class="" href="https://www.rabbitmq.com/docs/install-debian#apt-quick-start">covered in the Debian doc guide</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-migrate">How to Migrate<a href="https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving#how-to-migrate" class="hash-link" aria-label="Direct link to How to Migrate" title="Direct link to How to Migrate" translate="no">​</a></h2>
<p>To add the new repositories and their <a class="" href="https://www.rabbitmq.com/docs/signatures">signing key</a>, use the following scripts.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Ubuntu 24.04</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Ubuntu 22.04</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Ubuntu 20.04</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Debian Bookworm</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Debian Bullseye</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> gnupg apt-transport-https </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Team RabbitMQ's signing key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-1sLf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> gpg </span><span class="token parameter variable" style="color:#36acaa">--dearmor</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /usr/share/keyrings/com.rabbitmq.team.gpg </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Add apt repositories maintained by Team RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/apt/sources.list.d/rabbitmq.list </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Modern Erlang/OTP releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/ubuntu/noble noble main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/ubuntu/noble noble main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Latest RabbitMQ releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/ubuntu/noble noble main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/ubuntu/noble noble main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Update package indices</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install Erlang packages</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> erlang-base </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-runtime-tools erlang-snmp erlang-ssl </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install rabbitmq-server and its dependencies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> rabbitmq-server </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> --fix-missing</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> gnupg apt-transport-https </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Team RabbitMQ's signing key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-1sLf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> gpg </span><span class="token parameter variable" style="color:#36acaa">--dearmor</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /usr/share/keyrings/com.rabbitmq.team.gpg </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Add apt repositories maintained by Team RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/apt/sources.list.d/rabbitmq.list </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Modern Erlang/OTP releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/ubuntu/jammy jammy main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/ubuntu/jammy jammy main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Latest RabbitMQ releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/ubuntu/jammy jammy main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/ubuntu/jammy jammy main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Update package indices</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install Erlang packages</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> erlang-base </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-runtime-tools erlang-snmp erlang-ssl </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install rabbitmq-server and its dependencies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> rabbitmq-server </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> --fix-missing</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> gnupg apt-transport-https </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Team RabbitMQ's signing key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-1sLf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> gpg </span><span class="token parameter variable" style="color:#36acaa">--dearmor</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /usr/share/keyrings/com.rabbitmq.team.gpg </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Add apt repositories maintained by Team RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/apt/sources.list.d/rabbitmq.list </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Modern Erlang/OTP releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/ubuntu/focal focal main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/ubuntu/focal focal main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Latest RabbitMQ releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/ubuntu/focal focal main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/ubuntu/focal focal main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Update package indices</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install Erlang packages</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> erlang-base </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-runtime-tools erlang-snmp erlang-ssl </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install rabbitmq-server and its dependencies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> rabbitmq-server </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> --fix-missing</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> gnupg apt-transport-https </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Team RabbitMQ's signing key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-1sLf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> gpg </span><span class="token parameter variable" style="color:#36acaa">--dearmor</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /usr/share/keyrings/com.rabbitmq.team.gpg </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Add apt repositories maintained by Team RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/apt/sources.list.d/rabbitmq.list </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Modern Erlang/OTP releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/debian/bookworm bookworm main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/debian/bookworm bookworm main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Latest RabbitMQ releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/debian/bookworm bookworm main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/debian/bookworm bookworm main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Update package indices</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install Erlang packages</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> erlang-base </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-runtime-tools erlang-snmp erlang-ssl </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install rabbitmq-server and its dependencies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> rabbitmq-server </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> --fix-missing</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/sh</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> gnupg apt-transport-https </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Team RabbitMQ's signing key</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-1sLf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> gpg </span><span class="token parameter variable" style="color:#36acaa">--dearmor</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /usr/share/keyrings/com.rabbitmq.team.gpg </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Add apt repositories maintained by Team RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tee</span><span class="token plain"> /etc/apt/sources.list.d/rabbitmq.list </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token string" style="color:#e3116c">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Modern Erlang/OTP releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/debian/bullseye bullseye main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/debian/bullseye bullseye main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">## Latest RabbitMQ releases</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">##</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/debian/bullseye bullseye main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/debian/bullseye bullseye main</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">EOF</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Update package indices</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> update </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install Erlang packages</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> erlang-base </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-runtime-tools erlang-snmp erlang-ssl </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## Install rabbitmq-server and its dependencies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apt-get</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> rabbitmq-server </span><span class="token parameter variable" style="color:#36acaa">-y</span><span class="token plain"> --fix-missing</span><br></span></code></pre></div></div></div></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="changes-in-the-new-repositories">Changes In the New Repositories<a href="https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving#changes-in-the-new-repositories" class="hash-link" aria-label="Direct link to Changes In the New Repositories" title="Direct link to Changes In the New Repositories" translate="no">​</a></h2>
<p>The new repositories, <code>deb1.rabbitmq.com</code> and <code>deb2.rabbitmq.com</code>, are signed using <a class="" href="https://www.rabbitmq.com/docs/signatures">our team's standard signing key</a>
instead of of the keys used by their upstream Cloudsmith repositories.</p>
<p>For the distributions that are sufficiently old, the new repositories provide packages going back to RabbitMQ 3.10.x
and Erlang versions going back to 24 or 25. Newer distributions, such as Ubuntu 24.04, start with RabbitMQ 3.12.x
and Erlang 26. Note that even the 3.12.x series are <a class="" href="https://www.rabbitmq.com/release-information">entirely out of support by now</a>.
We <strong>strongly encourage</strong> everyone to move to the latest RabbitMQ 4.x series.</p>
<p>If you use <a class="" href="https://www.rabbitmq.com/docs/install-debian#apt-pinning">apt pinning</a>, note that the Origin field of the new repo has changed to <code>RabbitMQ</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="existing-repository-shutdown-schedule">Existing Repository Shutdown Schedule<a href="https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving#existing-repository-shutdown-schedule" class="hash-link" aria-label="Direct link to Existing Repository Shutdown Schedule" title="Direct link to Existing Repository Shutdown Schedule" translate="no">​</a></h2>
<p>The existing repos, <code>ppa1.rabbitmq.com</code> and <code>ppa2.rabbitmq.com</code>, will remain in operation <strong>until Nov 1, 2025</strong> but
will not receive any new updates. After Nov 1, 2025, these repositories will be shut down.</p>
<p>Please do not put off the migration, it is a matter of updating an apt repository definition file: the signing key used by the new repos
has been recommended for installing by our docs for years.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thank-you-cloudsmith">Thank you, Cloudsmith<a href="https://www.rabbitmq.com/blog/2025/07/16/debian-apt-repositories-are-moving#thank-you-cloudsmith" class="hash-link" aria-label="Direct link to Thank you, Cloudsmith" title="Direct link to Thank you, Cloudsmith" translate="no">​</a></h2>
<p><a href="https://cloudsmith.io/" target="_blank" rel="noopener noreferrer" class="">Cloudsmith.io</a> has been powering our <code>apt</code> and <code>dnf</code> (<code>yum</code>, RPM) repositories directly or as a mirror upstream
since 2016. For nearly a decade, Cloudsmith have offered us a reliable service and an API that's a pleasure to automate with.</p>]]></content:encoded>
            <category>Announcements</category>
            <category>Updates</category>
            <category>Releases</category>
        </item>
        <item>
            <title><![CDATA[Go Stream client 1.5.8 is released with a critical fix]]></title>
            <link>https://www.rabbitmq.com/blog/2025/07/04/go-stream-client-1.5.8-critical-fix</link>
            <guid>https://www.rabbitmq.com/blog/2025/07/04/go-stream-client-1.5.8-critical-fix</guid>
            <pubDate>Fri, 04 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ Go Stream client 1.5.8  is a newbug fix release that includes]]></description>
            <content:encoded><![CDATA[<p><a href="https://github.com/rabbitmq/rabbitmq-stream-go-client/releases/tag/v1.5.8" target="_blank" rel="noopener noreferrer" class="">RabbitMQ Go Stream client 1.5.8</a>  is a newbug fix release that includes
a <a href="https://github.com/rabbitmq/rabbitmq-stream-go-client/pull/411" target="_blank" rel="noopener noreferrer" class="">critical fix</a>.</p>
<p>The fix reverts the <a href="https://github.com/rabbitmq/rabbitmq-stream-go-client/pull/393" target="_blank" rel="noopener noreferrer" class="">pull request 393</a> that introduced a dangerous bug where the library skipped chunk delivery when the channel's maximum
capacity was reached. In practical terms, message dispatch to the application would stop.</p>
<p>The bug was triggered when the consumer was experiencing a near peak delivery pressure for some time,
or when the consumer was consistently slow to process the deliveries.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="affected-versions">Affected versions<a href="https://www.rabbitmq.com/blog/2025/07/04/go-stream-client-1.5.8-critical-fix#affected-versions" class="hash-link" aria-label="Direct link to Affected versions" title="Direct link to Affected versions" translate="no">​</a></h2>
<p>The bug affects the following versions: <code>1.5.5</code>, <code>1.5.6</code> and <code>1.5.7</code>.</p>
<p>We strongly recommend updating the client to <code>1.5.8</code> as soon as possible.</p>]]></content:encoded>
            <category>Streams</category>
            <category>Stream-clients</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ is not affected by CVE-2025-32433 (an Erlang/OTP CVE)]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/24/rabbitmq-is-not-affected-by-cve-2025-32433</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/24/rabbitmq-is-not-affected-by-cve-2025-32433</guid>
            <pubDate>Thu, 24 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ is not affected by CVE-2025-32433,]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ is not affected by <a href="https://github.com/erlang/otp/security/advisories/GHSA-37cp-fgq5-7wc2" target="_blank" rel="noopener noreferrer" class="">CVE-2025-32433</a>,
a vulnerability in the Erlang's SSH library. RabbitMQ does not use SSH, neither the server nor the client parts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="team-rabbitmqs-erlang-packages-do-not-include-ssh">Team RabbitMQ's Erlang Packages Do Not Include SSH<a href="https://www.rabbitmq.com/blog/2025/04/24/rabbitmq-is-not-affected-by-cve-2025-32433#team-rabbitmqs-erlang-packages-do-not-include-ssh" class="hash-link" aria-label="Direct link to Team RabbitMQ's Erlang Packages Do Not Include SSH" title="Direct link to Team RabbitMQ's Erlang Packages Do Not Include SSH" translate="no">​</a></h2>
<p>Team RabbitMQ produces <a href="https://github.com/rabbitmq/erlang-rpm/releases" target="_blank" rel="noopener noreferrer" class="">a zero dependency Erlang RPM</a>
that does not include the SSH library since it is not used. Our <a href="https://github.com/rabbitmq/erlang-debian-package" target="_blank" rel="noopener noreferrer" class="">Debian packages</a> are split into multiple fine-grained components,
and the RabbitMQ installation guide <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">skips SSH library installation</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="patched-versions-are-available">Patched Versions Are Available<a href="https://www.rabbitmq.com/blog/2025/04/24/rabbitmq-is-not-affected-by-cve-2025-32433#patched-versions-are-available" class="hash-link" aria-label="Direct link to Patched Versions Are Available" title="Direct link to Patched Versions Are Available" translate="no">​</a></h2>
<p>Team RabbitMQ's <a href="https://rabbitmq.com/docs/install-rpm" target="_blank" rel="noopener noreferrer" class="">RPM repositories</a> and <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">Debian repositories</a> were updated to include Erlang <code>27.3.3</code>, <code>26.2.5.11</code> and <code>25.3.2.20</code>.</p>
<p>For aarch64 (64-bit ARM) RPM packages, see <a href="https://github.com/rabbitmq/erlang-rpm/releases" target="_blank" rel="noopener noreferrer" class=""><code>rabbitmq/erlang-rpm</code> releases</a>.</p>
<p>For aarch64 (64-bit ARM) Debian packages of Erlang <code>26.2.5.11</code>, see <a href="https://launchpad.net/~rabbitmq/+archive/ubuntu/rabbitmq-erlang" target="_blank" rel="noopener noreferrer" class="">this Launchpad repository</a>.</p>
<p>RabbitMQ <a href="https://github.com/docker-library/rabbitmq" target="_blank" rel="noopener noreferrer" class="">community Docker image</a> was also upgraded to Erlang <code>27.3.3</code> and <code>26.2.5.11</code> last week.</p>]]></content:encoded>
            <category>security</category>
        </item>
        <item>
            <title><![CDATA[AMQP 1.0 over WebSocket]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket</guid>
            <pubDate>Wed, 16 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[We are delighted to announce support for AMQP 1.0 over WebSocket in VMware Tanzu RabbitMQ 4.1.]]></description>
            <content:encoded><![CDATA[<p>We are delighted to announce support for AMQP 1.0 over WebSocket in <a href="https://www.vmware.com/products/app-platform/tanzu-rabbitmq" target="_blank" rel="noopener noreferrer" class="">VMware Tanzu RabbitMQ</a> 4.1.</p>
<p>This feature enables any browser-based application to communicate with RabbitMQ using AMQP 1.0, paving the way for a wide range of efficient browser-based business messaging scenarios.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-websocket">What is WebSocket?<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#what-is-websocket" class="hash-link" aria-label="Direct link to What is WebSocket?" title="Direct link to What is WebSocket?" translate="no">​</a></h2>
<p>WebSocket, defined in <a href="https://datatracker.ietf.org/doc/html/rfc6455" target="_blank" rel="noopener noreferrer" class="">RFC 6455</a>, is a simple protocol consisting of two parts:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">Client                                   Server</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                                         |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |================ Part I =================|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |---- WebSocket Handshake Request -------&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       GET /some/path HTTP/1.1           |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Upgrade: websocket                |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Connection: Upgrade               |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Sec-WebSocket-Protocol: amqp      |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                                         |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;-- WebSocket Handshake Response --------|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       HTTP/1.1 101 Switching Protocols  |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Upgrade: websocket                |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Connection: Upgrade               |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |       Sec-WebSocket-Protocol: amqp      |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                                         |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |================ Part II ================|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;========= WebSocket Connection ========&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |        Full-duplex communication        |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                                         |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;---------- Binary Data [AMQP] ---------&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;---------- Binary Data [AMQP] ---------&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;---------- Binary Data [AMQP] ---------&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                 ...                     |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |                                         |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |----------- Close Frame ----------------&gt;|</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  |&lt;---------- Close Frame -----------------|</span><br></span></code></pre></div></div>
<p>The first part is the handshake, consisting of an HTTP request and response.
The second part is the data transfer:
a single TCP connection remains open between client and server, allowing either side to push binary data to the other at any time.</p>
<p>In this example, the binary data consists of <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#doc-idp31280" target="_blank" rel="noopener noreferrer" class="">AMQP frames</a> because the client proposed <code>Sec-WebSocket-Protocol: amqp</code> to the server, and the server accepted it.
The <code>Sec-WebSocket-Protocol</code> header specifies the application-level protocol layered over WebSocket.</p>
<p>The protocol stack for this communication looks like this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">|      AMQP         |  Application Layer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">|    WebSocket      |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">|       TCP         |  Transport Layer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">|       IP          |  Network Layer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">|     Ethernet      |  Link Layer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+-------------------+</span><br></span></code></pre></div></div>
<p>The WebSocket protocol itself does not dictate the application-layer protocol, allowing for flexibility.
It could support any protocol, including STOMP and MQTT.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-websocket">Why WebSocket?<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#why-websocket" class="hash-link" aria-label="Direct link to Why WebSocket?" title="Direct link to Why WebSocket?" translate="no">​</a></h2>
<p>WebSocket provides the following advantages:</p>
<ol>
<li class=""><strong>Browser Compatibility:</strong>
It allows browser-based applications to use application-layer protocols other than HTTP.
For security reasons, browsers restrict JavaScript from opening raw TCP connections to communicate using protocols like AMQP or MQTT.
WebSocket protects against malicious JavaScript running in a browser, therefore enabling secure application-layer communication over the WebSocket layer.</li>
<li class=""><strong>Firewall traversal:</strong>
WebSocket facilitates communication in environments with restrictive firewall rules.
For example, while port 443 (<code>https</code>) may be allowed, port <a class="" href="https://www.rabbitmq.com/docs/networking#ports">5671</a> for <code>amqps</code> might be blocked.
In such cases, a secure WebSocket (<code>wss</code>) connection on port 443 can be used to communicate over AMQP.</li>
</ol>
<p>Modern browsers universally support WebSocket, making it a practical choice for web-based applications.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="websocket-in-rabbitmq">WebSocket in RabbitMQ<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#websocket-in-rabbitmq" class="hash-link" aria-label="Direct link to WebSocket in RabbitMQ" title="Direct link to WebSocket in RabbitMQ" translate="no">​</a></h2>
<p>RabbitMQ has long supported <a class="" href="https://www.rabbitmq.com/docs/web-stomp">STOMP over WebSocket</a> and <a class="" href="https://www.rabbitmq.com/docs/web-mqtt">MQTT over WebSocket</a> through the <code>rabbitmq_web_stomp</code> and <code>rabbitmq_web_mqtt</code> plugins, respectively.</p>
<p>VMware Tanzu RabbitMQ 4.1 introduces the new <code>rabbitmq_web_amqp</code> plugin, compliant with the <a href="https://docs.oasis-open.org/amqp-bindmap/amqp-wsb/v1.0/cs01/amqp-wsb-v1.0-cs01.html" target="_blank" rel="noopener noreferrer" class="">AMQP WebSocket Binding Committee Specification 01</a>.
This plugin operates similarly to the existing WebSocket plugins, starting a listener to manage WebSocket protocol aspects.</p>
<p>Previously, browser-based applications connected to RabbitMQ using MQTT or STOMP over WebSocket, often due to the lack of AMQP support.
AMQP over WebSocket brings the following benefits:</p>
<ul>
<li class=""><strong>Feature Richness:</strong>
Unlike MQTT and STOMP which are designed for simplicity, AMQP is a protocol designed for business messaging supporting more advanced features.</li>
<li class=""><strong>Efficiency</strong>:
AMQP is binary and efficient, whereas STOMP is text-oriented.</li>
</ul>
<p>This makes AMQP over WebSocket an excellent choice for efficient, feature-rich browser-based business messaging.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="websocket-relay">WebSocket Relay<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#websocket-relay" class="hash-link" aria-label="Direct link to WebSocket Relay" title="Direct link to WebSocket Relay" translate="no">​</a></h2>
<p>Before this plugin, a workaround involved using a WebSocket relay.
A relay would accept WebSocket connections from clients and open separate TCP connections to RabbitMQ.
While functional, this approach introduced downsides such as:</p>
<ol>
<li class="">Additional latency from the extra network hop.</li>
<li class="">Increased resource usage to maintain two TCP connections per client.</li>
<li class="">Operational overhead for deploying and monitoring the relay.</li>
<li class="">An additional potential point of failure.</li>
</ol>
<p>The new plugin eliminates these issues by providing direct AMQP over WebSocket support.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example">Example<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no">​</a></h2>
<p>RabbitMQ includes plugins <code>rabbitmq_web_stomp_examples</code> and <code>rabbitmq_web_mqtt_examples</code> with basic examples called <a class="" href="https://www.rabbitmq.com/blog/2012/05/14/introducing-rabbitmq-web-stomp#the-usage">"echo" and "bunny"</a>.
Similarly, VMware Tanzu RabbitMQ 4.1 introduces <code>rabbitmq_web_amqp_examples</code>.</p>
<p>The AMQP over WebSocket "bunny" example works as follows:</p>
<ol>
<li class="">The <code>rabbitmq_web_amqp_examples</code> plugin creates a <a class="" href="https://www.rabbitmq.com/docs/streams">stream</a> named <code>amq.web_amqp_examples.bunny</code>.</li>
<li class="">When visiting <code>http://localhost:15670/web-amqp-examples/bunny.html</code>, the plugin serves files <code>bunny.html</code>, <code>bunny.png</code>, and <code>rhea.js</code>.
The <code>bunny.html</code> file displays the <code>bunny.png</code>.
Additionally, the <code>bunny.html</code> file contains JavaScript code which creates an AMQP over WebSocket connection from the browser to RabbitMQ:</li>
</ol>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// default AMQP over WebSocket port and path in RabbitMQ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ws://"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">hostname</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">":15678/ws"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> ws </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">websocket_connect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">WebSocket</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> connection </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">connect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"connection_details"</span><span class="token operator" style="color:#393A34">:</span><span class="token function" style="color:#d73a49">ws</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"amqp"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Setting username without password causes rhea to use SASL mechanism ANONYMOUS.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"username"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ignored"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>This code snippet uses the <code>rhea.js</code> file.
<a href="https://github.com/amqp/rhea" target="_blank" rel="noopener noreferrer" class="">rhea</a> is an open source AMQP 1.0 TypeScript/JavaScript library.
This single file can be created by running the following commands in the root directory of the <code>rhea</code> repository:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">make</span><span class="token plain"> browserify</span><br></span></code></pre></div></div>
<p>Not only did the browser open an AMQP over WebSocket connection, but it also created a <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#section-sessions" target="_blank" rel="noopener noreferrer" class="">session</a> and <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#section-links" target="_blank" rel="noopener noreferrer" class="">links</a> to/from the pre-declared stream:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> address </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/queues/"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"connection_open"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sender </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">connection</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">open_sender</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">address</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// If we open a new brower tab, we want to see the existing drawing.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> filter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string-property property" style="color:#36acaa">'my-filter'</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> amqp_types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">wrap_described</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"first"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rabbitmq:stream-offset-spec"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">connection</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">open_receiver</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">source</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">address</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> address</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">filter</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> filter</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p></p><figure><img decoding="async" loading="lazy" alt="AMQP over WebSocket connection" src="https://www.rabbitmq.com/assets/images/web-amqp-connection-2183f67ea4970cc2f168aefd49361ae8.png" width="3046" height="2198" class="img_ev3q"><figcaption>AMQP over WebSocket connection</figcaption></figure><p></p>
<ol start="3">
<li class="">If you open a second browser tab at the same URL, it also creates an AMQP over WebSocket connection publishing to and consuming from the same stream.</li>
<li class="">When you draw on either of the two browser tabs, the other tab sees the live drawing because both tabs consume from the same stream:</li>
</ol>
<p></p><figure><img decoding="async" loading="lazy" alt="Bunny Example" src="https://www.rabbitmq.com/assets/images/amqp-bunnies-19369c48b6c4c151d3506c3e0e4590a1.png" width="3570" height="1450" class="img_ev3q"><figcaption>Bunny Example</figcaption></figure><p></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clients">Clients<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#clients" class="hash-link" aria-label="Direct link to Clients" title="Direct link to Clients" translate="no">​</a></h2>
<p>As an alternative to <a href="https://github.com/amqp/rhea" target="_blank" rel="noopener noreferrer" class="">rhea</a>, you can use the <a href="https://github.com/coders51/rabbitmq-amqp-js-client" target="_blank" rel="noopener noreferrer" class=""><strong>RabbitMQ</strong> AMQP 1.0 JavaScript library</a>.
As explained in the <a class="" href="https://www.rabbitmq.com/blog/2024/08/05/native-amqp#rabbitmq-amqp-10-clients">Native AMQP 1.0</a> blog post, RabbitMQ libraries include RabbitMQ specific features such as declaring <a class="" href="https://www.rabbitmq.com/tutorials/amqp-concepts#exchanges">exchanges</a>, <a class="" href="https://www.rabbitmq.com/tutorials/amqp-concepts#queues">queues</a>, and <a class="" href="https://www.rabbitmq.com/tutorials/amqp-concepts#bindings">bindings</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="wrapping-up">Wrapping up<a href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket#wrapping-up" class="hash-link" aria-label="Direct link to Wrapping up" title="Direct link to Wrapping up" translate="no">​</a></h2>
<p>VMware Tanzu RabbitMQ 4.1 enables browsers to communicate with RabbitMQ using AMQP 1.0.</p>
<p>Please note: the new AMQP over WebSocket plugin is a closed-source feature available exclusively in the commercial <a href="https://www.vmware.com/products/app-platform/tanzu-rabbitmq" target="_blank" rel="noopener noreferrer" class="">VMware Tanzu RabbitMQ</a> offering.
It is not part of the open source RabbitMQ distribution.</p>
<p>While this blog post illustrated the feature with a playful example involving a bunny, AMQP 1.0 is an efficient protocol built for business messaging.
Think of enterprise tools like Salesforce, Workday, or Jira - all running in the browser and benefiting from real-time messaging.</p>]]></content:encoded>
            <category>AMQP 1.0</category>
            <category>Web Messaging</category>
            <category>RabbitMQ 4.1</category>
            <category>New Features</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.1.0 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released</guid>
            <pubDate>Tue, 15 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.1.0 is]]></description>
            <content:encoded><![CDATA[<p><a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.1.0" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.1.0</code></a> is
a new minor release that includes <a class="" href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements">multiple performance improvements</a>,
and a number of features such as thew <a class="" href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery">new peer discovery mechanism for Kubernetes</a>.</p>
<p>See Compatibility Notes below to learn about <strong>breaking or potentially breaking changes</strong> in this release.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="highlights">Highlights<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h2>
<p>Some key improvements in this release are listed below.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="quorum-queue-throughput-and-parallelism-improvements">Quorum Queue Throughput and Parallelism Improvements<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#quorum-queue-throughput-and-parallelism-improvements" class="hash-link" aria-label="Direct link to Quorum Queue Throughput and Parallelism Improvements" title="Direct link to Quorum Queue Throughput and Parallelism Improvements" translate="no">​</a></h3>
<p>Quorum queue log reads are now offloaded to channels (sessions, connections).</p>
<p>In practical terms this means improved consumer throughput, lower interference of publishers
on queue delivery rate to consumers, and improved CPU core utilization by each quorum queue
(assuming there are enough cores available to the node).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="initial-support-for-amqp-10-filter-expressions">Initial Support for AMQP 1.0 Filter Expressions<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#initial-support-for-amqp-10-filter-expressions" class="hash-link" aria-label="Direct link to Initial Support for AMQP 1.0 Filter Expressions" title="Direct link to Initial Support for AMQP 1.0 Filter Expressions" translate="no">​</a></h3>
<p>Support for the <code>properties</code> and <code>application-properties</code> filters of <a href="https://groups.oasis-open.org/higherlogic/ws/public/document?document_id=66227" target="_blank" rel="noopener noreferrer" class="">AMQP Filter Expressions Version 1.0 Working Draft 09</a>.</p>
<p>As described in the <a href="https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions" target="_blank" rel="noopener noreferrer" class="">AMQP 1.0 Filter Expressions</a> blog post,
this feature enables multiple concurrent clients each consuming only a subset of messages from a stream while maintaining message order.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="feature-flags-quality-of-life-improvements">Feature Flags Quality of Life Improvements<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#feature-flags-quality-of-life-improvements" class="hash-link" aria-label="Direct link to Feature Flags Quality of Life Improvements" title="Direct link to Feature Flags Quality of Life Improvements" translate="no">​</a></h3>
<p>Graduated (mandatory) <a href="https://www.rabbitmq.com/docs/feature-flags" target="_blank" rel="noopener noreferrer" class="">feature flags</a> several minors ago has proven that they could use some user experience improvements.
For example, certain required feature flags will now be enabled on node boot when all nodes in the cluster support them.</p>
<p>See core server changes below as well as the <a href="https://github.com/orgs/rabbitmq/projects/4/views/1" target="_blank" rel="noopener noreferrer" class="">GitHub project dedicated to feature flags improvements</a>
for the complete list of related changes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rabbitmqadmin-v2">rabbitmqadmin v2<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#rabbitmqadmin-v2" class="hash-link" aria-label="Direct link to rabbitmqadmin v2" title="Direct link to rabbitmqadmin v2" translate="no">​</a></h3>
<p><a class="" href="https://www.rabbitmq.com/docs/management-cli"><code>rabbitmqadmin</code> v2</a> is a major revision of the
original CLI client for the RabbitMQ HTTP API.</p>
<p>It supports a much broader set of operations, including health checks, operations
on federation upstreams, shovels, transformations of exported definitions,
(some) Tanzu RabbitMQ HTTP API endpoints, <code>--long-option</code> and subcommand inference in interactive mode,
and more.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="breaking-changes-and-compatibility-notes">Breaking Changes and Compatibility Notes<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#breaking-changes-and-compatibility-notes" class="hash-link" aria-label="Direct link to Breaking Changes and Compatibility Notes" title="Direct link to Breaking Changes and Compatibility Notes" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="initial-amqp-0-9-1-maximum-frame-size">Initial AMQP 0-9-1 Maximum Frame Size<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#initial-amqp-0-9-1-maximum-frame-size" class="hash-link" aria-label="Direct link to Initial AMQP 0-9-1 Maximum Frame Size" title="Direct link to Initial AMQP 0-9-1 Maximum Frame Size" translate="no">​</a></h3>
<p>Before a client connection can negotiate a maximum frame size (<code>frame_max</code>), it must authenticate
successfully. Before the authenticated phase, a special lower <code>frame_max</code> value
is used.</p>
<p>With this release, the value was increased from the original 4096 bytes to 8192
to accommodate larger <a href="https://www.rabbitmq.com/docs/oauth2" target="_blank" rel="noopener noreferrer" class="">JWT tokens</a>.</p>
<p>Clients that do override <code>frame_max</code> now must use values of 8192 bytes or greater.
We recommend using the default server value of <code>131072</code>: do not override the <code>frame_max</code>
key in <code>rabbitmq.conf</code> and do not set it in the application code.</p>
<p><a href="https://github.com/amqp-node/amqplib/" target="_blank" rel="noopener noreferrer" class=""><code>amqplib</code></a> is a popular client library that has been using
a low <code>frame_max</code> default of <code>4096</code>. Its users must <a href="https://github.com/amqp-node/amqplib/blob/main/CHANGELOG.md#v0107" target="_blank" rel="noopener noreferrer" class="">upgrade to a compatible version</a>
(starting with <code>0.10.7</code>) or explicitly use a higher <code>frame_max</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mqtt">MQTT<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#mqtt" class="hash-link" aria-label="Direct link to MQTT" title="Direct link to MQTT" translate="no">​</a></h3>
<ul>
<li class="">
<p>The default MQTT <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901086" target="_blank" rel="noopener noreferrer" class="">Maximum Packet Size</a> changed from 256 MiB to 16 MiB.</p>
<p>This default can be overridden by <a href="https://www.rabbitmq.com/docs/configure#config-file" target="_blank" rel="noopener noreferrer" class="">configuring</a> <code>mqtt.max_packet_size_authenticated</code>.
Note that this value must not be greater than <code>max_message_size</code> (which also defaults to 16 MiB).</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="etcd-peer-discovery">etcd Peer Discovery<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#etcd-peer-discovery" class="hash-link" aria-label="Direct link to etcd Peer Discovery" title="Direct link to etcd Peer Discovery" translate="no">​</a></h3>
<p>The following <code>rabbitmq.conf</code> settings are unsupported:</p>
<ul>
<li class=""><code>cluster_formation.etcd.ssl_options.fail_if_no_peer_cert</code></li>
<li class=""><code>cluster_formation.etcd.ssl_options.dh</code></li>
<li class=""><code>cluster_formation.etcd.ssl_options.dhfile</code></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="erlangotp-compatibility-notes">Erlang/OTP Compatibility Notes<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#erlangotp-compatibility-notes" class="hash-link" aria-label="Direct link to Erlang/OTP Compatibility Notes" title="Direct link to Erlang/OTP Compatibility Notes" translate="no">​</a></h2>
<p>This release <a class="" href="https://www.rabbitmq.com/docs/which-erlang">requires Erlang 26.2</a> and supports Erlang 27.x.</p>
<p><a class="" href="https://www.rabbitmq.com/docs/which-erlang#erlang-repositories">Provisioning Latest Erlang Releases</a> explains
what package repositories and tools can be used to provision latest patch versions of Erlang 26.x and 27.x.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts">Release Artifacts<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#release-artifacts" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Artifacts for preview releases are distributed via GitHub releases:</p>
<ul>
<li class="">In main repository, <a href="https://github.com/rabbitmq/rabbitmq-server/releases" target="_blank" rel="noopener noreferrer" class=""><code>rabbitmq/rabbitmq-server</code></a></li>
<li class="">In the development builds repository, <a href="https://github.com/rabbitmq/server-packages/releases" target="_blank" rel="noopener noreferrer" class=""><code>rabbitmq/server-packages</code></a></li>
</ul>
<p>There is a <code>4.1.0</code> preview version of the <a href="https://github.com/docker-library/rabbitmq" target="_blank" rel="noopener noreferrer" class="">community RabbitMQ image</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrading-to-410">Upgrading to 4.1.0<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#upgrading-to-410" class="hash-link" aria-label="Direct link to Upgrading to 4.1.0" title="Direct link to Upgrading to 4.1.0" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-guides-on-upgrades">Documentation guides on upgrades<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#documentation-guides-on-upgrades" class="hash-link" aria-label="Direct link to Documentation guides on upgrades" title="Direct link to Documentation guides on upgrades" translate="no">​</a></h3>
<p>See the <a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">Upgrading guide</a> for documentation on upgrades and <a href="https://github.com/rabbitmq/rabbitmq-server/releases" target="_blank" rel="noopener noreferrer" class="">GitHub releases</a>
for release notes of individual releases.</p>
<p>This release series supports upgrades from <code>4.0.x</code> and <code>3.13.x</code>.</p>
<p><a href="https://www.rabbitmq.com/docs/blue-green-upgrade" target="_blank" rel="noopener noreferrer" class="">Blue/Green Deployment</a>-style upgrades are available for migrations
from RabbitMQ <code>3.12.x</code> series.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-required-feature-flags">New Required Feature Flags<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#new-required-feature-flags" class="hash-link" aria-label="Direct link to New Required Feature Flags" title="Direct link to New Required Feature Flags" translate="no">​</a></h3>
<p>None. The required feature flag set is the same as in <code>4.0.x</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mixed-version-cluster-compatibility">Mixed version cluster compatibility<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#mixed-version-cluster-compatibility" class="hash-link" aria-label="Direct link to Mixed version cluster compatibility" title="Direct link to Mixed version cluster compatibility" translate="no">​</a></h3>
<p>RabbitMQ 4.1.0 nodes can run alongside <code>4.0.x</code> nodes. <code>4.1.x</code>-specific features can only be made available when all nodes in the cluster
upgrade to 4.1.0 or a later patch release in the new series.</p>
<p>While operating in mixed version mode, some aspects of the system may not behave as expected. The list of known behavior changes will be covered in future updates.
Once all nodes are upgraded to 4.1.0, these irregularities will go away.</p>
<p>Mixed version clusters are a mechanism that allows rolling upgrade and are not meant to be run for extended
periods of time (no more than a few hours).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="recommended-post-upgrade-procedures">Recommended Post-upgrade Procedures<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#recommended-post-upgrade-procedures" class="hash-link" aria-label="Direct link to Recommended Post-upgrade Procedures" title="Direct link to Recommended Post-upgrade Procedures" translate="no">​</a></h3>
<p>This version does not require any additional post-upgrade procedures
compared to other versions.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts-1">Release Artifacts<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#release-artifacts-1" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Release artifacts can be obtained on <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.9" target="_blank" rel="noopener noreferrer" class="">GitHub</a>
as well as <a href="https://www.rabbitmq.com/docs/install-rpm" target="_blank" rel="noopener noreferrer" class="">RPM</a>, <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">Debian</a> package repositories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="community-support-now-only-covers-the-41x-series">Community Support Now Only Covers the 4.1.x Series<a href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released#community-support-now-only-covers-the-41x-series" class="hash-link" aria-label="Direct link to Community Support Now Only Covers the 4.1.x Series" title="Direct link to Community Support Now Only Covers the 4.1.x Series" translate="no">​</a></h2>
<p>With the release of <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.1.0" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.1.0</code></a>, this series is
no longer covered by <a class="" href="https://www.rabbitmq.com/release-information">community support</a>.</p>
<p>Future <code>4.0.x</code> releases will only be available to <a class="" href="https://www.rabbitmq.com/contact">paying customers</a>
via the Broadcom customer portal.</p>
<p>All non-paying users must <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.1.0" target="_blank" rel="noopener noreferrer" class="">upgrade to <code>4.1.0</code></a>
in order to be covered by community support from the core team.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 4.1</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.0.9 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/14/rabbitmq-4.0.9-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/14/rabbitmq-4.0.9-is-released</guid>
            <pubDate>Mon, 14 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.0.9 is]]></description>
            <content:encoded><![CDATA[<p><a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.9" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.0.9</code></a> is
a new patch release in the <code>4.0.x</code> series.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts">Release Artifacts<a href="https://www.rabbitmq.com/blog/2025/04/14/rabbitmq-4.0.9-is-released#release-artifacts" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Release artifacts can be obtained on <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.9" target="_blank" rel="noopener noreferrer" class="">GitHub</a>
as well as <a class="" href="https://www.rabbitmq.com/docs/install-rpm">RPM</a>, <a class="" href="https://www.rabbitmq.com/docs/install-debian">Debian</a> package repositories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="community-support-now-only-covers-the-41x-series">Community Support Now Only Covers the 4.1.x Series<a href="https://www.rabbitmq.com/blog/2025/04/14/rabbitmq-4.0.9-is-released#community-support-now-only-covers-the-41x-series" class="hash-link" aria-label="Direct link to Community Support Now Only Covers the 4.1.x Series" title="Direct link to Community Support Now Only Covers the 4.1.x Series" translate="no">​</a></h2>
<p>With the release of <a class="" href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released">RabbitMQ <code>4.1.0</code></a>, this series is
no longer covered by <a href="https://www.rabbitmq.com/release-information" target="_blank" rel="noopener noreferrer" class="">community support</a>.</p>
<p>Future <code>4.0.x</code> releases will only be available to <a class="" href="https://www.rabbitmq.com/contact">paying customers</a>
via the Broadcom customer portal.</p>
<p>All non-paying users must <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.1.0" target="_blank" rel="noopener noreferrer" class="">upgrade to <code>4.1.0</code></a>
in order to be covered by community support from the core team.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-guidance">Upgrade Guidance<a href="https://www.rabbitmq.com/blog/2025/04/14/rabbitmq-4.0.9-is-released#upgrade-guidance" class="hash-link" aria-label="Direct link to Upgrade Guidance" title="Direct link to Upgrade Guidance" translate="no">​</a></h2>
<p>If <a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a> from a version prior to 4.0, please consult
the <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.1" target="_blank" rel="noopener noreferrer" class=""><code>4.0</code> release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 4.0</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.1 Performance Improvements]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements</guid>
            <pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.1 is around the corner (update: has been released)]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ 4.1 <a class="" href="https://www.rabbitmq.com/blog/2025/04/15/rabbitmq-4.1.0-is-released">is around the corner</a> (update: has been released)
and, as usual, apart from new features, we have made some internal changes that should provide better performance.</p>
<p>There are at least 4 notable changes:</p>
<ol>
<li class="">Lower and more stable memory usage for quorum queues</li>
<li class="">Much better performance when consuming a long quorum queue</li>
<li class="">Better performance for Websocket connections</li>
<li class="">Lower memory usage and/or higher throughput for TCP connections</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quorum-queues-lower-memory-usage">Quorum Queues: Lower Memory Usage<a href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements#quorum-queues-lower-memory-usage" class="hash-link" aria-label="Direct link to Quorum Queues: Lower Memory Usage" title="Direct link to Quorum Queues: Lower Memory Usage" translate="no">​</a></h2>
<p>Quorum queues in RabbitMQ 4.1 should use less memory in many situations. As you may be aware,
<a class="" href="https://www.rabbitmq.com/docs/4.0/quorum-queues#how-memory-wal-and-segments-files-interact">in the past quorum queues had a sawtooth-like memory usage pattern</a>.
They would fill up an in-memory buffer (cache) for recent <a href="https://raft.github.io/" target="_blank" rel="noopener noreferrer" class="">Raft</a> operations and once full,
the buffer was emptied and then filled up again.</p>
<p>In RabbitMQ 4.1, these entries are deleted much more frequently, leading to a more stable memory usage
under many conditions. Here's the memory usage of a cluster initially running 4.0 and then upgraded
to 4.1:</p>
<p></p><figure><img decoding="async" loading="lazy" alt="Memory usage of a cluster before/after upgrading from 4.0 to 4.1" src="https://www.rabbitmq.com/assets/images/qq-memory-usage-94f1748d6a2ab574ee67845844d9de36.png" width="4066" height="1992" class="img_ev3q"><figcaption>Memory usage of a cluster before/after upgrading from 4.0 to 4.1</figcaption></figure><p></p>
<p>The exact details of the workload are not super important, since this difference should be visible
for many different workloads, but for completeness, here they are:</p>
<ul>
<li class="">there were 10 quorum queues</li>
<li class="">all messages were 1kb in size</li>
<li class="">each queue received 500 messages per second from a single publisher (so 5000 messages per second total for all queues)</li>
<li class="">each queue had a single consumer (a vast majority of messages was consumed within 10 milliseconds since being published)</li>
<li class="">the queues were effectively empty, since all messages were promptly consumed</li>
</ul>
<p>It's worth remembering that such a low and stable memory usage cannot be expected
in all conditions. For example, <a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#message-metadata" target="_blank" rel="noopener noreferrer" class="">quorum queues keep metadata about messages in the queue in memory</a>
and therefore, if you have
many messages in the queues (messages are not immediately consumed), this metadata will
consume memory. There are also other factors and in-memory structures that will grow based on the workload.
Nevertheless, memory usage should be lower and less spiky in many common situations.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quorum-queues-offloading-disk-reads">Quorum Queues: Offloading Disk Reads<a href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements#quorum-queues-offloading-disk-reads" class="hash-link" aria-label="Direct link to Quorum Queues: Offloading Disk Reads" title="Direct link to Quorum Queues: Offloading Disk Reads" translate="no">​</a></h2>
<p>Let's consider a completely different workload - one where messages accumulate in the queues
and then consumers need to catch up to empty the queues. Historically, quorum queues could get overwhelmed
by an influx of consumers, especially if the messages were large and consumers requested a lot of them
(either they had a large prefetch buffer or there were a lot of consumers, or both).
In this scenario, the queue could get so busy reading the older messages from disk (to dispatch them to the consumers)
that publishers had to wait quite a bit to have their messages accepted by the queue.</p>
<p>In RabbitMQ 4.1, such disk reads are offloaded to the AMQP 0.9.1 channel or AMQP 1.0 session processes
(based on the protocol used). The queue has much less work to do and can keep serving
the publishers.</p>
<p>Let's take a look at the differences in publishing and consumption rates between 4.0 and 4.1:</p>
<p></p><figure><img decoding="async" loading="lazy" alt="Influx of consumers, 4.0 to 4.1" src="https://www.rabbitmq.com/assets/images/qq-disk-read-offload-f6233b4fe7a209a5dcb218b1b55b1ad0.png" width="2026" height="1220" class="img_ev3q"><figcaption>Influx of consumers, 4.0 to 4.1</figcaption></figure><p></p>
<p>Here's what's going on in this graph:</p>
<ol>
<li class="">We have two clusters running, 4.0 (green lines) and 4.1 (yellow)</li>
<li class="">Both clusters receive ~6000 messages per second, each message is 20kb</li>
<li class="">Initially, there are no consumers; hence, the consumption rate is zero</li>
<li class="">After some time, consumers start and try to consume messages</li>
<li class="">In each environment, there are are now 10 consumers, each with a 300 message prefetch buffer</li>
<li class="">4.0 environment is overwhelmed - the publishing rate drops to just ~100 messages per second</li>
<li class="">Meanwhile, 4.1 environment continues serving the publishers with no noticeable impact</li>
<li class="">Additionally, the consumption rate is almost double in the 4.1 environment</li>
<li class="">Once the backlog of messages is consumed, both environments can handle ~7000 messages per second in and out</li>
</ol>
<p>Not only are the publishers not throttled, but the consumers are also able to consume the messages much faster!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="better-performance-of-websocket-connections">Better Performance of WebSocket Connections<a href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements#better-performance-of-websocket-connections" class="hash-link" aria-label="Direct link to Better Performance of WebSocket Connections" title="Direct link to Better Performance of WebSocket Connections" translate="no">​</a></h2>
<p>To serve HTTP connections, RabbitMQ uses a popular Erlang HTTP server called <a href="https://github.com/ninenines/cowboy" target="_blank" rel="noopener noreferrer" class="">Cowboy</a>
(developed by <a href="https://github.com/essen" target="_blank" rel="noopener noreferrer" class="">Loïc Hoguin</a> long before he joined the RabbitMQ team).
RabbitMQ 4.1 upgrades Cowboy to version 2.13.0, which <a href="https://ninenines.eu/articles/cowboy-2.13.0-performance/" target="_blank" rel="noopener noreferrer" class="">significantly improves WebSocket
performance</a> for all systems that rely on Cowboy,
including RabbitMQ. Upgrading to RabbitMQ 4.1 should therefore be particularly beneficial to anyone using
<a class="" href="https://www.rabbitmq.com/blog/2025/04/16/amqp-websocket">AMQP</a>, <a href="https://www.rabbitmq.com/docs/web-mqtt" target="_blank" rel="noopener noreferrer" class="">MQTT</a> or <a href="https://www.rabbitmq.com/docs/web-stomp" target="_blank" rel="noopener noreferrer" class="">STOMP</a> over WebSocket.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tcp-buffer-auto-tuning">TCP Buffer Auto-Tuning<a href="https://www.rabbitmq.com/blog/2025/04/08/4.1-performance-improvements#tcp-buffer-auto-tuning" class="hash-link" aria-label="Direct link to TCP Buffer Auto-Tuning" title="Direct link to TCP Buffer Auto-Tuning" translate="no">​</a></h2>
<p>A key improvement described in
<a href="https://ninenines.eu/articles/cowboy-2.13.0-performance/" target="_blank" rel="noopener noreferrer" class="">Cowboy 2.13.0 release blog post</a>
is the dynamic TCP buffer auto-tuning. For WebSocket connections, these improvements
in Cowboy automatically benefit RabbitMQ users, since Cowboy handles HTTP connections to RabbitMQ.</p>
<p>In RabbitMQ 4.1, we incorporated the same TCP buffer auto-tuning mechanism into the AMQP listener,
which is a completely separate code path and does not
use Cowboy (since Cowboy is an HTTP server). Thanks to this work, RabbitMQ should use less memory for AMQP
0.9.1 and 1.0 connections, without a noticeable performance penalty. The amount of memory saved depends on
your current buffer size and the number of connections, but in our tests it saved a few hundred megabytes
of memory in a system with a few thousand connections.</p>
<p>It's worth pointing out that the buffer discussed in this paragraph is a user-space buffer and should
not be confused with <code>recbuf</code> / <code>sndbuf</code> buffers which are kernel buffers. These can be
<a href="https://www.rabbitmq.com/docs/networking#tuning-for-throughput-tcp-buffers" target="_blank" rel="noopener noreferrer" class="">statically configured</a>
and if they are not, they are auto-tuned by the Linux kernel (the behaviour on other operating systems
may differ).</p>
<p>The value of <code>tcp_listen_options.buffer</code>, which used to control the size of the now auto-tuned buffer,
is ignored.</p>]]></content:encoded>
            <category>Announcements</category>
            <category>performance</category>
            <category>RabbitMQ 4.1</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.1: New Kubernetes Peer Discovery Mechanism]]></title>
            <link>https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery</link>
            <guid>https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery</guid>
            <pubDate>Fri, 04 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.1 includes a completely redesigned peer discovery plugin for Kubernetes.]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ 4.1 includes a completely redesigned peer discovery plugin for Kubernetes.
No configuration changes should be needed when upgrading to 4.1, so if you want,
you can just stop reading here. If you are interested in the details, read on.
This blog post explains the peer discovery subsystem in general
and the changes to <code>rabbitmq_peer_discovery_k8s</code> in particular.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-peer-discovery">What Is Peer Discovery?<a href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery#what-is-peer-discovery" class="hash-link" aria-label="Direct link to What Is Peer Discovery?" title="Direct link to What Is Peer Discovery?" translate="no">​</a></h2>
<p>Say you want to have a 3-node RabbitMQ cluster - you start 3 instances of RabbitMQ but then
what? You can manually tell two of them to join the third one using
<code>rabbitmqctl join_cluster</code> command and voilà, you have a 3-node cluster.</p>
<p>Most users would prefer this process to be automated however. That's where
peer discovery comes in. There is a handful of peer discovery plugins available in RabbitMQ
for different situations. The simplest one is called
<a href="https://www.rabbitmq.com/docs/cluster-formation#peer-discovery-classic-config" target="_blank" rel="noopener noreferrer" class="">classic peer discovery</a>
and allows you to just put the hostnames of the nodes in the configuration file,
so that RabbitMQ automatically initiates the cluster formation with them upon startup.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>It is a common misconception that the peer discovery is performed every time a node starts.
This is not the case, it is only performed when a node starts for the first time
(when it has an empty data folder).</p></div></div>
<p>However, based on how you deploy RabbitMQ, the hostnames may not be known upfront.
Even if they are, you need a different configuration file for each cluster, which
may be inconvenient if you want a quick way to spin up new clusters for testing
environments for example.</p>
<p>In such cases, you can use other peer discovery plugins, which allow nodes to register
with some external systems such as Consul or etcd and query these systems for a list
of registered nodes. This way you don't need to know the hostnames upfront - the nodes
discover each other automatically.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kubernetes-peer-discovery-before-rabbitmq-41">Kubernetes Peer Discovery before RabbitMQ 4.1<a href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery#kubernetes-peer-discovery-before-rabbitmq-41" class="hash-link" aria-label="Direct link to Kubernetes Peer Discovery before RabbitMQ 4.1" title="Direct link to Kubernetes Peer Discovery before RabbitMQ 4.1" translate="no">​</a></h2>
<p>Before RabbitMQ 4.1, <code>rabbitmq_peer_discovery_k8s</code> performed the peer discovery by querying
the Kubernetes API server for a list of endpoints behind a service (Kubernetes automatically
registers pods of a given StatefulSet as endpoints). However, there were a few issues with
this approach:</p>
<ol>
<li class="">some users reported that occasionally, cluster formation would fail and the pods
would form multiple separate clusters; we never received enough data to diagnose this issue
and it never occurred in our testing (we tried thousands of times...)</li>
<li class="">it required permissions to query the Kubernetes API; not a big deal, but it was unnecessary
and some security-conscious users were asking why we needed this</li>
<li class="">it was a convoluted way of asking a question, we already know the answer to...</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kubernetes-peer-discovery-in-rabbitmq-41">Kubernetes Peer Discovery in RabbitMQ 4.1<a href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery#kubernetes-peer-discovery-in-rabbitmq-41" class="hash-link" aria-label="Direct link to Kubernetes Peer Discovery in RabbitMQ 4.1" title="Direct link to Kubernetes Peer Discovery in RabbitMQ 4.1" translate="no">​</a></h2>
<p>When deploying RabbitMQ to Kubernetes, you should always use a StatefulSet.
All pods that belong to a StatefulSet are named consistently with the name of the StatefulSet,
followed by a hyphen and an
<a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#ordinal-index" target="_blank" rel="noopener noreferrer" class="">ordinal index</a>.
The ordinal index start is configurable, but is almost always <code>0</code>, so let's just assume it is <code>0</code>.
Given that, a 3-node cluster deployed to Kubernetes will always have nodes with suffixes <code>-0</code>, <code>-1</code> and <code>-2</code>.
There's no need to query the Kubernetes API to know this!</p>
<p>The new plugin doesn't perform any Kubernetes API queries. It just assumes that a pod with <code>-0</code> suffix
will exist and treats it as the "seed" node. All other nodes will join the cluster by joining
the <code>-0</code> node. If the <code>-0</code> node is not up, other nodes will wait forever for it to come up
(they will never form a cluster without the <code>-0</code> node). Remember that peer discovery only
happens when a node starts for the first time, so "waiting forever for node <code>-0</code>" only
applies to the first time you deploy a given cluster.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="advanced-configuration">Advanced Configuration<a href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery#advanced-configuration" class="hash-link" aria-label="Direct link to Advanced Configuration" title="Direct link to Advanced Configuration" translate="no">​</a></h3>
<p>For the vast majority of users, this upgrade should be completely transparent. First of all,
since peer discovery is only performed when a node starts for the first time,
if you upgrade an existing cluster, peer discovery changes won't affect you.</p>
<p>Second, the new plugin accepts, but ignores, all configuration options of the old plugin. You will
see some warnings in the logs about deprecated options being used, but you can safely ignore them.</p>
<p>If the default configuration doesn't work for you, there are two settings you can use:</p>
<ol>
<li class="">
<p>If you are using an ordinal start other than <code>0</code> (and seriously, why would you?!), you should
configure the plugin by setting <code>cluster_formation.k8s.ordinal_start = N</code> where <code>N</code> is the ordinal start.
When set, all nodes will try to join the <code>-N</code> node, rather than the <code>-0</code> node.</p>
</li>
<li class="">
<p>Additionally, you can set <code>cluster_formation.k8s.seed_node = rabbit@seed-node-hostname</code> to
just say what the seed node is. We don't expect this setting to ever be needed, but it's there
if you really need it.</p>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-if-im-using-the-cluster-operator">What If I'm Using The Cluster Operator?<a href="https://www.rabbitmq.com/blog/2025/04/04/new-k8s-peer-discovery#what-if-im-using-the-cluster-operator" class="hash-link" aria-label="Direct link to What If I'm Using The Cluster Operator?" title="Direct link to What If I'm Using The Cluster Operator?" translate="no">​</a></h3>
<p><a href="https://www.rabbitmq.com/kubernetes/operator/operator-overview#cluster-operator" target="_blank" rel="noopener noreferrer" class="">Cluster Operator</a>
is the recommended way of deploying RabbitMQ to Kubernetes, so if you are using it - great.
You should be able to continue using it with no changes. You will see the aforementioned warnings in the logs,
because the Cluster Operator allows deploying different RabbitMQ versions, not just 4.1.
Therefore, for the time being, it will continue setting values required by the old version of
<code>rabbitmq_peer_discovery_k8s</code> in the configuration file. Such a configuration works for both 4.1 and older
versions. At some point in the future, Cluster Operator will drop support for RabbitMQ versions older
than 4.1 and we'll remove these settings from the ConfigMap declared by the Cluster Operator.</p>]]></content:encoded>
            <category>Announcements</category>
            <category>kubernetes</category>
            <category>RabbitMQ 4.1</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.0.7 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/02/26/rabbitmq-4.0.7-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/02/26/rabbitmq-4.0.7-is-released</guid>
            <pubDate>Wed, 26 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.0.7]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rabbitmq-407">RabbitMQ 4.0.7<a href="https://www.rabbitmq.com/blog/2025/02/26/rabbitmq-4.0.7-is-released#rabbitmq-407" class="hash-link" aria-label="Direct link to RabbitMQ 4.0.7" title="Direct link to RabbitMQ 4.0.7" translate="no">​</a></h2>
<p><a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.7" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.0.7</code></a> is
a new patch release in the <code>4.0.x</code> series.</p>
<p>This series is currently covered by <a href="https://www.rabbitmq.com/release-information" target="_blank" rel="noopener noreferrer" class="">community support</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts">Release Artifacts<a href="https://www.rabbitmq.com/blog/2025/02/26/rabbitmq-4.0.7-is-released#release-artifacts" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Release artifacts can be obtained on <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.7" target="_blank" rel="noopener noreferrer" class="">GitHub</a>
as well as <a href="https://www.rabbitmq.com/docs/install-rpm" target="_blank" rel="noopener noreferrer" class="">RPM</a>, <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">Debian</a> package repositories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-guidance">Upgrade Guidance<a href="https://www.rabbitmq.com/blog/2025/02/26/rabbitmq-4.0.7-is-released#upgrade-guidance" class="hash-link" aria-label="Direct link to Upgrade Guidance" title="Direct link to Upgrade Guidance" translate="no">​</a></h2>
<p>If <a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a> from a version prior to 4.0, please consult
the <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.1" target="_blank" rel="noopener noreferrer" class=""><code>4.0</code> release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 4.0</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.0.6 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/02/11/rabbitmq-4.0.6-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/02/11/rabbitmq-4.0.6-is-released</guid>
            <pubDate>Tue, 11 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.0.6]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rabbitmq-406">RabbitMQ 4.0.6<a href="https://www.rabbitmq.com/blog/2025/02/11/rabbitmq-4.0.6-is-released#rabbitmq-406" class="hash-link" aria-label="Direct link to RabbitMQ 4.0.6" title="Direct link to RabbitMQ 4.0.6" translate="no">​</a></h2>
<p><a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.6" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.0.6</code></a> is
a new patch release in the <code>4.0.x</code> series.</p>
<p>This series is currently covered by <a href="https://www.rabbitmq.com/release-information" target="_blank" rel="noopener noreferrer" class="">community support</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts">Release Artifacts<a href="https://www.rabbitmq.com/blog/2025/02/11/rabbitmq-4.0.6-is-released#release-artifacts" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Release artifacts can be obtained on <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.6" target="_blank" rel="noopener noreferrer" class="">GitHub</a>
as well as <a href="https://www.rabbitmq.com/docs/install-rpm" target="_blank" rel="noopener noreferrer" class="">RPM</a>, <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">Debian</a> package repositories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-guidance">Upgrade Guidance<a href="https://www.rabbitmq.com/blog/2025/02/11/rabbitmq-4.0.6-is-released#upgrade-guidance" class="hash-link" aria-label="Direct link to Upgrade Guidance" title="Direct link to Upgrade Guidance" translate="no">​</a></h2>
<p>If <a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a> from a version prior to 4.0, please consult
the <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.1" target="_blank" rel="noopener noreferrer" class=""><code>4.0</code> release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 4.0</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 3.13.8 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/02/07/rabbitmq-3.13.8-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/02/07/rabbitmq-3.13.8-is-released</guid>
            <pubDate>Fri, 07 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 3.13.8 is a new patch release in the 3.13.x series.]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ <code>3.13.8</code> is a new patch release in the <code>3.13.x</code> series.
This series is currently covered by <a href="https://www.rabbitmq.com/release-information" target="_blank" rel="noopener noreferrer" class="">commercial support</a> only.</p>
<p>For publicly available open source releases, see the <a href="https://www.rabbitmq.com/blog/tags/rabbit-mq-4-0" target="_blank" rel="noopener noreferrer" class=""><code>4.0.x</code> series</a>.</p>
<h1>Release Artifacts</h1>
<p>Release artifacts for the <code>3.13.x</code> series can be obtained via the <a href="https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/open-source-rabbitmq/3-13/opn-src-rabbitmq/site-install.html" target="_blank" rel="noopener noreferrer" class="">Broadcom customer portal</a>.</p>
<h1>Upgrade Guidance</h1>
<p>If&nbsp;<a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a>&nbsp;from a version prior to 3.13.9, please consult the&nbsp;<a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.13.0" target="_blank" rel="noopener noreferrer" class="">3.13.0&nbsp;release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 3.13</category>
        </item>
        <item>
            <title><![CDATA[Tanzu RabbitMQ 3.13.8 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2025/02/07/tanzu-rabbitmq-3.13.8-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2025/02/07/tanzu-rabbitmq-3.13.8-is-released</guid>
            <pubDate>Fri, 07 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Tanzu RabbitMQ 3.13.8 is a new patch release in the 3.13.x series of]]></description>
            <content:encoded><![CDATA[<p><a href="https://support.broadcom.com/group/ecx/productfiles?subFamily=VMware%20Tanzu%20RabbitMQ&amp;displayGroup=VMware%20Tanzu%20RabbitMQ&amp;release=3.13.8&amp;os=&amp;servicePk=527640&amp;language=EN" target="_blank" rel="noopener noreferrer" class="">Tanzu RabbitMQ <code>3.13.8</code></a> is a new patch release in the <code>3.13.x</code> series of
the <a href="https://www.vmware.com/products/app-platform/tanzu-rabbitmq" target="_blank" rel="noopener noreferrer" class="">commercial edition of RabbitMQ</a>.</p>
<p>This edition includes additional feature such as Warm Standby Replication, intra-cluster traffic
compression and a FIPS-enabled Erlang runtime.</p>
<p>Tanzu RabbitMQ is available <a href="https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/tanzu-rabbitmq-on-kubernetes/3-13/tanzu-rabbitmq-kubernetes/overview.html" target="_blank" rel="noopener noreferrer" class="">on Kubernetes</a>, as an <a href="https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/tanzu-rabbitmq-oci/3-13/tanzu-rabbitmq-oci-image/overview.html" target="_blank" rel="noopener noreferrer" class="">OCI image</a>,
and an <a href="https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/tanzu-rabbitmq-ova/3-13/tanzu-rabbitmq-ova-virtual-machine/overview.html" target="_blank" rel="noopener noreferrer" class="">OVA image</a>.</p>
<p>This release is based on open source RabbitMQ <code>3.13.x</code> and includes all the latest backports
in <a href="https://www.rabbitmq.com/blog/2025/02/07/rabbitmq-3.13.8-is-released" target="_blank" rel="noopener noreferrer" class="">open source RabbitMQ <code>3.13.8</code></a>.</p>
<h1>Release Artifacts</h1>
<p>Release artifacts for the <code>3.13.x</code> series can be obtained via the <a href="https://support.broadcom.com/" target="_blank" rel="noopener noreferrer" class="">Broadcom customer portal</a>:</p>
<ul>
<li class=""><a href="https://support.broadcom.com/group/ecx/productfiles?subFamily=VMware%20Tanzu%20RabbitMQ&amp;displayGroup=VMware%20Tanzu%20RabbitMQ&amp;release=3.13.8&amp;os=&amp;servicePk=527640&amp;language=EN" target="_blank" rel="noopener noreferrer" class="">Artifacts</a></li>
<li class="">Tanzu RabbitMQ <a href="https://support.broadcom.com/group/ecx/productfiles?subFamily=VMware%20Tanzu%20RabbitMQ%20on%20Kubernetes&amp;displayGroup=VMware%20Tanzu%20RabbitMQ%20on%20Kubernetes&amp;release=3.13.8&amp;os=&amp;servicePk=527733&amp;language=EN" target="_blank" rel="noopener noreferrer" class="">on Kubernetes</a></li>
</ul>
<h1>Upgrade Guidance</h1>
<p>If&nbsp;<a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a>&nbsp;from a version prior to 3.13.9, please first consult the&nbsp;<a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.13.0" target="_blank" rel="noopener noreferrer" class="">open source RabbitMQ 3.13.0&nbsp;release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>Tanzu RabbitMQ</category>
            <category>RabbitMQ 3.13</category>
        </item>
        <item>
            <title><![CDATA[How Are The Messages Stored? Not in Memory!]]></title>
            <link>https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored</link>
            <guid>https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored</guid>
            <pubDate>Fri, 17 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[It's time to retire the myth that RabbitMQ stores messages in memory. While it was true in the early days of RabbitMQ,]]></description>
            <content:encoded><![CDATA[<p>It's time to retire the myth that RabbitMQ stores messages in memory. While it was true in the early days of RabbitMQ,
and an option for the last 10 years, modern RabbitMQ versions almost always write messages
to disk right away. In this blog post we review how different queue types store messages but the short answer is: not in memory!</p>
<p>Let's start by clarifying what we mean by storing messages in memory, since it is not a precise statement.
If interpreted as "RabbitMQ uses memory to process messages", this phrase is certainly true.
When client applications send data to RabbitMQ, that data appears in memory buffers first (that's true for all
network-based software). It is also true, that RabbitMQ might cache some messages in memory,
for example to improve performance (again, true for virtually all software that needs to serve data).</p>
<p>However, I keep hearing this phrase used to express concerns about message durability - if you power off the server,
your messages will be lost! In this context, modern RabbitMQ versions almost never store messages in memory.</p>
<div class="theme-admonition theme-admonition-important admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>important</div><div class="admonitionContent_BuS1"><p>There is no configuration in which publishing 1GB of messages to RabbitMQ with no connected consumers,
would lead to 1GB of memory being used to store these messages. Some subset of messages can be cached in memory,
but messages are stored on disk.</p></div></div>
<p>We'll go through different queue types and discuss how the messages are processed, stored and when they are confirmed
to the publishers. Publisher confirmations are critical here - RabbitMQ doesn't offer guarantees for messages that
were not confirmed. If you haven't received the confirmation, you can't even know whether the message reached
RabbitMQ (the network connection could have failed for example). With that in mind, let's go through the different queue types.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="classic-queues">Classic Queues<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#classic-queues" class="hash-link" aria-label="Direct link to Classic Queues" title="Direct link to Classic Queues" translate="no">​</a></h2>
<p><a href="https://www.rabbitmq.com/docs/classic-queues" target="_blank" rel="noopener noreferrer" class="">Classic queues</a> is the oldest kind of queues in RabbitMQ and the main source of "RabbitMQ stores messages in memory" misconception.
RabbitMQ was first released in 2007. Disks were significantly slower back then and therefore classic queues were designed
to try to avoid writing messages to disk. There was a whole bunch of settings to configure when RabbitMQ should
write messages to disk (a process called "paging") so it would not keep messages in memory indefinitely but indeed,
you could say RabbitMQ stored messages in memory back then. However, that was a long time ago.</p>
<p>In RabbitMQ 3.6, released in 2015, the "lazy mode" was introduced. A queue configured to be lazy, always
stored messages on disk and didn't keep them in memory at all. This means that "RabbitMQ stores messages in memory"
was not true 10 years ago. It'd still do this by default, but it was completely optional.</p>
<p>Lazy mode was removed in RabbitMQ in 3.12, released in 2023, but the default (and the only available) behaviour
changed and is similar to the lazy mode, although not exactly the same. Therefore, for over a year now, classic queues don't store
messages in memory and can't even be configured to do so. The myth is almost entirely false at this point.</p>
<p>Almost entirely? So here's how classic queues work right now: they accumulate incoming messages in a small in-memory buffer
and write them to disk as a batch, as soon as the in-memory buffer is full. Since we don't know if more messages will come,
there are additional triggers that flush that buffer, including a flush after a certain number of batched messages
(even if they are too small to use the whole buffer) and after
a certain number of operations on that batch is performed. Additionally, the queue monitors how quickly messages are consumed
and makes decisions based on that (if there are fast consumers, more messages will be cached in memory). Finally, there's the
last-resort trigger which will flush the buffer every 200ms. So the absolute maximum of how long a message can be stored in
memory is 200ms but in practice, I've never seen this happen. Publishers usually receive confirms within a few milliseconds
and they are sent only after the message was written to disk.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="but-i-see-no-disk-activity-when-i-use-a-classic-queue">But I See No Disk Activity When I Use a Classic Queue!<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#but-i-see-no-disk-activity-when-i-use-a-classic-queue" class="hash-link" aria-label="Direct link to But I See No Disk Activity When I Use a Classic Queue!" title="Direct link to But I See No Disk Activity When I Use a Classic Queue!" translate="no">​</a></h3>
<p>Indeed, it's entirely possible to publish messages to classic queues and see virtually no disk writes nor disk reads.
How is that possible? It's an optimisation for a very specific, but relatively common case. As explained above, messages
can be briefly kept in memory but if there are active consumers that are waiting for messages (their prefetch buffer is not full),
messages that reach the queue are dispatched to the consumers immediately, without waiting for their batch to be written to disk.
A message that gets acknowledged by the consumer before this message's batch is written to disk, will not be written to disk at all,
because it simply doesn't need to be. Queues don't store acknowledged messages, so if the message is acknowledged before it is written,
it doesn't get written. If it's acknowledged after it was written, it's deleted from the queue (the actual removal from disk
will happen later, asynchronously, but it is considered deleted immediately).</p>
<p>It's worth mentioning that classic queues have <a href="https://www.rabbitmq.com/blog/2024/01/11/3.13-release#classic-queues-storage-primer" target="_blank" rel="noopener noreferrer" class="">two separate storage mechanisms</a>.
Messages below 4kb (configurable through <code>queue_index_embed_msgs_below</code>) are stored in a per-queue message store and messages above that threshold
are stored in a per-vhost message store. The optimisation mentioned above only works for messages that would be stored in the per-queue message store.</p>
<p>So here it is, in modern RabbitMQ versions, classic queues store messages in memory for a very short period of time (milliseconds)
and no more than 200ms for sure. They may not write messages to disk at all, if the messages are small,
and consumed quickly enough, but this is just a performance optimisation. I'll leave it up to you to decide if that
qualifies as "RabbitMQ stores messages in memory", but I think a more accurate statement would be "when a message is delivered to
a classic queue, RabbitMQ writes messages to disk with a short delay". But yes, that means that for a brief moment, they are only in memory.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="surely-transient-messages-are-stored-in-memory">Surely, Transient Messages Are Stored in Memory?<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#surely-transient-messages-are-stored-in-memory" class="hash-link" aria-label="Direct link to Surely, Transient Messages Are Stored in Memory?" title="Direct link to Surely, Transient Messages Are Stored in Memory?" translate="no">​</a></h3>
<p>No. Again, things were different in the past but as of RabbitMQ 4.0, the only difference between persistent and transient messages
is when RabbitMQ sends back the publisher confirm. The messages are stored the same way as described above.</p>
<p>For persistent messages, the confirm is sent when either of these two events takes place:</p>
<ol>
<li class="">The message is written to disk</li>
<li class="">The message is delivered and acknowledged by a consumer (if that happens before it's written to disk)</li>
</ol>
<p>For transient messages, the confirm is sent as soon as the message reaches the queue and enters the in-memory buffer.
Since the message is transient, the guarantees are lax: the queue received the message, the publisher can move on.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-about-fsync">What About fsync?<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#what-about-fsync" class="hash-link" aria-label="Direct link to What About fsync?" title="Direct link to What About fsync?" translate="no">​</a></h3>
<p><code>fsync</code> is a low-level file system operation that should ensure that messages are really written to disk.
There are multiple layers of I/O buffers between a user-space process such as RabbitMQ and actual hardware, including operating
system buffers and internal disk buffers. Performing a write without performing <code>fsync</code> doesn't guarantee that the data
will survive a sudden power loss. Unfortunately, <code>fsync</code> is a relatively slow operation, so any I/O intensive software has to
decide if, and when, to call it. While classic queues call <code>fsync</code> in some cases (for example, when RabbitMQ stops gracefully),
fsync is not performed before publisher confirms are sent. Therefore, even durable messages that a publisher received a confirmation for,
can technically be lost if the server crashes. If you need stronger guarantees, you can use <a class="" href="https://www.rabbitmq.com/docs/quorum-queues">quorum queues</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quorum-queues">Quorum Queues<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#quorum-queues" class="hash-link" aria-label="Direct link to Quorum Queues" title="Direct link to Quorum Queues" translate="no">​</a></h2>
<p>From the initial release in RabbitMQ 3.8 (released in 2019), <a href="https://www.rabbitmq.com/docs/quorum-queues" target="_blank" rel="noopener noreferrer" class="">quorum queues</a> always stored
messages on disk. While the initial versions had an additional in-memory <strong>cache</strong> for messages, it was removed in RabbitMQ 3.10.</p>
<p>The situation is therefore simple: if the publisher received a confirmation, this means the message had already been
written to disk and <code>fsync</code>-ed on the quorum of nodes (in the most common scenario of a 3-node cluster, that means
it was written and <code>fsync</code>-ed on at least 2 nodes).</p>
<p>Since RabbitMQ doesn't offer any guarantees for messages that have not been confirmed to publishers, we could pretty much stop here.
However, for the sake of completeness, I'll mention that some messages are technically in memory:</p>
<ol>
<li class="">The queue process has a mailbox (an Erlang/OTP concept) where requests to the queue process (such as enqueue/dequeue operations)
arrive for processing. The quorum queue process receives messages from the mailbox and processes them as a batch. When there's
a lot of requests, these operations may accumulate in the mailbox and therefore, assuming there are enqueue operations there, at this
point, some messages are only in-memory. However, this generally means RabbitMQ is at least briefly overloaded and
either way, these operations are usually processed within a few milliseconds. Plus, these messages are not confirmed yet.</li>
<li class="">Quorum queues rely on the <a href="https://raft.github.io/" target="_blank" rel="noopener noreferrer" class="">Raft protocol</a> and our <a href="https://github.com/rabbitmq/ra/" target="_blank" rel="noopener noreferrer" class="">Raft implementations</a>
stores the most recent Raft operations in memory. For enqueue operations this means that the message is in memory as well. However,
at this point the message is already written to disk and <code>fsync</code>-ed or it hasn't been confirmed yet.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="streams">Streams<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#streams" class="hash-link" aria-label="Direct link to Streams" title="Direct link to Streams" translate="no">​</a></h2>
<p>With <a href="https://www.rabbitmq.com/docs/streams" target="_blank" rel="noopener noreferrer" class="">Streams</a>, the situation is even simpler than with quorum queues: Streams never supported keeping messages in memory, period.
The main difference between queues and stream in general, is that streams can be read multiple times and therefore consuming
a message doesn't remove that message from a stream. There's no point in storing messages only in memory, if we need to be able
to deliver them to consumers multiple times, potentially long after they were published.</p>
<p>Streams do not perform <code>fsync</code>, since they were optimised for high message throughput.</p>
<p>For completeness, just like quorum queues (and any other Erlang process), the stream process has a mailbox where requests to the stream
process arrive. There's therefore a moment where the messages are stored in memory for a short time. Once again though,
these are messages that have not been confirmed yet and they rarely stay in memory for more than a few milliseconds.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mqtt-qos-0-queues">MQTT QoS 0 Queues<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#mqtt-qos-0-queues" class="hash-link" aria-label="Direct link to MQTT QoS 0 Queues" title="Direct link to MQTT QoS 0 Queues" translate="no">​</a></h2>
<p>RabbitMQ 3.12 introduced <a class="" href="https://www.rabbitmq.com/blog/2023/03/21/native-mqtt">Native MQTT support</a>, and as part of that work, a new queue type was introduced,
specifically for MQTT QoS 0 consumers (you can't explicitly declare a queue of this type, you have to create an MQTT QoS 0 subscription).
Since QoS 0 basically means best-effort but no guarantees, QoS 0 messages are not written to disk at all and are delivered directly to the
consumers that are present. Effectively, there's no queue at all (beyond the Erlang mailbox). Messages received from the publisher are
immediately delivered to the consumers and removed from memory.</p>
<p>Does this qualify as storing messages in memory? I'd say it doesn't - the messages are in memory initially, simply because
that's how computers work, and are removed from memory as soon as they are delivered to the consumers. We don't really store
them in memory - we just process them and never write them to disk in this case. You can disagree and say that this is exactly
what "storing messages in memory means" but even then - this only applies to MQTT QoS 0 usage and the messages will generally stay
in memory for no more than a fraction of second.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="message-metadata">Message Metadata<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#message-metadata" class="hash-link" aria-label="Direct link to Message Metadata" title="Direct link to Message Metadata" translate="no">​</a></h2>
<p>So far I focused on message bodies, since that's what people usually mean when talking about storing messages in memory. However,
RabbitMQ also needs to keep track of the messages that are currently present in the queues. For example, when a queues has a defined
<a href="https://www.rabbitmq.com/docs/maxlength" target="_blank" rel="noopener noreferrer" class=""><code>x-max-length</code> limit</a>, RabbitMQ needs to keep track of the total size of all the messages in the queue,
so when it delivers a message, it keeps the message size (but not the message body itself) in memory, to just subtract it quickly
from the total size of the queue, once the consumer acknowledges the messages.</p>
<p>This kind of metadata is stored differently by different queue type, but even when stored in memory, it will consume
significantly less memory than the message bodies would and doesn't change any guarantees about the message durability.</p>
<p>Here's how we store the metadata for different queue types:</p>
<ul>
<li class="">Classic queues<!-- -->
<ul>
<li class="">for messages stored in the per-queue message store, no data is stored in memory</li>
<li class="">for messages stored in the per-vhost message store, there's some metadata in memory</li>
</ul>
</li>
<li class="">Quorum queues<!-- -->
<ul>
<li class="">metadata is stored in memory (at least 32 bytes per message, sometimes a bit more, for example when <a href="https://www.rabbitmq.com/docs/ttl" target="_blank" rel="noopener noreferrer" class="">message TTL</a> is used)</li>
</ul>
</li>
<li class="">Streams<!-- -->
<ul>
<li class="">no message metadata is stored in memory</li>
</ul>
</li>
</ul>
<p>This basically means that for messages under 4KB stored in classic queues, as well as for streams, regardless of how many messages
there are in the queue/stream, the memory usage is constant. You will run out disk before you run out of memory (you should
configure <a href="https://www.rabbitmq.com/docs/streams#retention" target="_blank" rel="noopener noreferrer" class="">retention</a>/<a href="https://www.rabbitmq.com/docs/maxlength" target="_blank" rel="noopener noreferrer" class="">length</a> limits
to avoid running out disk, but that's a different story).</p>
<p>Here's an illustration highlighting the difference between the two classic queue storage mechanisms. In this test,
I first published 1 million messages of 4000 bytes each, then deleted the queue and published 1 million messages of 4100 bytes
each. As you can see, the memory usage was stable in the first phase (small fluctuations notwithstanding), but when publishing
larger messages, we can see the memory usage grows as well. This is because 4100 bytes is above the threshold, so these
messages are stored in the per-vhost message store and the per-vhost message store keeps some metadata in memory. A million 4KB
messages would have taken up 4GB of memory to store, while the actual usage is still below 400MB.</p>
<p></p><figure><img decoding="async" loading="lazy" alt="Classic Queues: memory usage when publishing small and large messages" src="https://www.rabbitmq.com/assets/images/classic-queues-899b1a1caebc83614d77525cf6f9d800.png" width="2556" height="938" class="img_ev3q"><figcaption>Classic Queues: memory usage when publishing small and large messages</figcaption></figure><p></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://www.rabbitmq.com/blog/2025/01/17/how-are-the-messages-stored#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>Here's the summary of the key points.</p>
<table><thead><tr><th>Type</th><th>When are the messages written to disk?</th><th>fsync?</th><th>When is the publisher confirm sent?</th></tr></thead><tbody><tr><td>Classic</td><td>After a few milliseconds or as soon as the in-memory buffer is full (whichever happens first)</td><td>No</td><td><strong>Durable messages</strong>: when the message is written to disk or consumed &amp; acknowledged <br> <strong>Transient messages</strong>: as soon as batched in memory</td></tr><tr><td>Quorum</td><td>Immediately (except for unconfirmed messages waiting in the mailbox, see above for details)</td><td>Yes</td><td>When written to disk and fsynced by the quorum of nodes (most commonly 2 out of 3 nodes)</td></tr><tr><td>Streams</td><td>Immediately (except for unconfirmed messages waiting in the mailbox, see above for details)</td><td>No</td><td>When written to disk by the quorum of nodes (most commonly 2 out of 3 nodes)</td></tr></tbody></table>
<p>The flexibility provided by RabbitMQ, with support for multiple protocols, queue types and other configurations (eg. single node,
vs a cluster with queue replication), combined with 18 years of history and evolution, means that almost any "RabbitMQ does/doesn't do X"
statement is incorrect or at least imprecise. They should almost always be quantified with a specific version and configuration.</p>
<p>Going back to the title of this post, I think it's fair to say that "RabbitMQ doesn't store messages in memory" is much
closer to the truth, than the opposite claim, which still circulates in discussions involving RabbitMQ. Regardless of the queue type,
there is no configuration in which publishing, say, 1GB of messages to RabbitMQ with no connected consumers, would lead to 1GB of memory being
used to store these messages. Most importantly, if you want high data safety guarantees, quorum queues are available and store data safely
by default. If you publish a message to a quorum queue and receive the confirmation, it'd take a disastrous event for RabbitMQ to lose it
(and if you want to protect messages from disastrous events, you might be interested in the commercial
<a href="https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/tanzu-rabbitmq-on-kubernetes/4-0/tanzu-rabbitmq-kubernetes/standby-replication.html" target="_blank" rel="noopener noreferrer" class="">Warm Standby Replication plugin</a>).</p>
<p>If you don't need such data safety guarantees, you don't have to pay the intrinsic overhead of data safety. Just use the right tool for the job.</p>]]></content:encoded>
            <category>Classic Queues</category>
            <category>Quorum Queues</category>
            <category>Streams</category>
        </item>
        <item>
            <title><![CDATA[Security Best Practices: epmd]]></title>
            <link>https://www.rabbitmq.com/blog/2024/12/18/epmd-public-exposure</link>
            <guid>https://www.rabbitmq.com/blog/2024/12/18/epmd-public-exposure</guid>
            <pubDate>Wed, 18 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Security Best Practices: epmd]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="security-best-practices-epmd">Security Best Practices: epmd<a href="https://www.rabbitmq.com/blog/2024/12/18/epmd-public-exposure#security-best-practices-epmd" class="hash-link" aria-label="Direct link to Security Best Practices: epmd" title="Direct link to Security Best Practices: epmd" translate="no">​</a></h2>
<p>The Erlang Port Mapper Daemon (<code>epmd</code>) is a built-in component that helps Erlang-based applications (including RabbitMQ) discover each other’s distribution ports.
Together with DNS for hostname resolution, <code>epmd</code> is a piece of infrastructure RabbitMQ nodes rely on for clustering, inter-node communication
and CLI tools connectivity.</p>
<p>While <code>epm</code> is very limited in scope, its exposure to the public Internet often means that Erlang distribution ports are also exposed.
This creates a potential security risk: if attackers find these distribution ports, they'd be one secret value away from being able to run
CLI commands against the node (or cluster).</p>
<p>Recent scans have revealed over 85,000 instances of publicly accessible <code>epmd</code>, with roughly half associated with RabbitMQ servers.</p>
<p>Fortunately, all it usually takes to mitigate this risk is limiting network access to a range of ports. <code>epmd</code> and inter-node communication
can also be limited to local network interfaces, in particular for single node clusters used for running tests.</p>
<p>Read the full article on the <a href="https://erlef.org/blog/eef/epmd-public-exposure" target="_blank" rel="noopener noreferrer" class="">Erlang Ecosystem Foundation blog</a>.</p>]]></content:encoded>
            <category>security</category>
        </item>
        <item>
            <title><![CDATA[RabbitMQ 4.0.5 is released]]></title>
            <link>https://www.rabbitmq.com/blog/2024/12/16/rabbitmq-4.0.5-is-released</link>
            <guid>https://www.rabbitmq.com/blog/2024/12/16/rabbitmq-4.0.5-is-released</guid>
            <pubDate>Mon, 16 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.0.5]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rabbitmq-405">RabbitMQ 4.0.5<a href="https://www.rabbitmq.com/blog/2024/12/16/rabbitmq-4.0.5-is-released#rabbitmq-405" class="hash-link" aria-label="Direct link to RabbitMQ 4.0.5" title="Direct link to RabbitMQ 4.0.5" translate="no">​</a></h2>
<p><a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.5" target="_blank" rel="noopener noreferrer" class="">RabbitMQ <code>4.0.5</code></a> is
a new patch release in the <code>4.0.x</code> series.</p>
<p>This series is currently covered by <a href="https://www.rabbitmq.com/release-information" target="_blank" rel="noopener noreferrer" class="">community support</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="release-artifacts">Release Artifacts<a href="https://www.rabbitmq.com/blog/2024/12/16/rabbitmq-4.0.5-is-released#release-artifacts" class="hash-link" aria-label="Direct link to Release Artifacts" title="Direct link to Release Artifacts" translate="no">​</a></h2>
<p>Release artifacts can be obtained on <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.5" target="_blank" rel="noopener noreferrer" class="">GitHub</a> as well as <a href="https://www.rabbitmq.com/docs/install-rpm" target="_blank" rel="noopener noreferrer" class="">RPM</a>, <a href="https://www.rabbitmq.com/docs/install-debian" target="_blank" rel="noopener noreferrer" class="">Debian</a> package repositories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-guidance">Upgrade Guidance<a href="https://www.rabbitmq.com/blog/2024/12/16/rabbitmq-4.0.5-is-released#upgrade-guidance" class="hash-link" aria-label="Direct link to Upgrade Guidance" title="Direct link to Upgrade Guidance" translate="no">​</a></h2>
<p>If <a href="https://www.rabbitmq.com/docs/upgrade" target="_blank" rel="noopener noreferrer" class="">upgrading</a> from a version prior to 4.0, please consult
the <a href="https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.1" target="_blank" rel="noopener noreferrer" class=""><code>4.0</code> release notes</a>.</p>]]></content:encoded>
            <category>Releases</category>
            <category>RabbitMQ 4.0</category>
        </item>
        <item>
            <title><![CDATA[AMQP 1.0 Filter Expressions]]></title>
            <link>https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions</link>
            <guid>https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions</guid>
            <pubDate>Fri, 13 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[RabbitMQ 4.1 introduces an exciting new feature: AMQP filter expressions for streams.]]></description>
            <content:encoded><![CDATA[<p>RabbitMQ 4.1 <a href="https://github.com/rabbitmq/rabbitmq-server/pull/12415" target="_blank" rel="noopener noreferrer" class="">introduces</a> an exciting new feature: AMQP filter expressions for <a class="" href="https://www.rabbitmq.com/docs/streams">streams</a>.</p>
<p>This feature enables RabbitMQ to support multiple concurrent clients, each consuming only a specific subset of messages while preserving message order.
Additionally, it minimizes network traffic between RabbitMQ and its clients by dispatching only the messages that match the clients' interests.</p>
<p>In this blog post, we’ll explore what AMQP filter expressions are and walk through a simple Java example of how to use them.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="specification">Specification<a href="https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions#specification" class="hash-link" aria-label="Direct link to Specification" title="Direct link to Specification" translate="no">​</a></h2>
<p>As outlined in the <a class="" href="https://www.rabbitmq.com/blog/2024/08/05/native-amqp">Native AMQP 1.0</a> blog post, one of AMQP 1.0's strengths is its extensibility, supported by numerous extension specifications.
RabbitMQ 4.1 takes advantage of the extension specification <a href="https://groups.oasis-open.org/higherlogic/ws/public/document?document_id=66227" target="_blank" rel="noopener noreferrer" class="">AMQP Filter Expressions Version 1.0 Working Draft 09</a>.</p>
<p>This specification defines AMQP type definitions for message filter expressions.
Filter expressions are predicates evaluated against a message, returning either <code>true</code> or <code>false</code>.
If a predicate evaluates to <code>true</code>, the broker dispatches the message to the consumer.</p>
<p>RabbitMQ 4.1 implements a subset of this specification, including:</p>
<ul>
<li class=""><strong>§ 4.2.4 properties filter</strong>: Applies to the immutable <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-properties" target="_blank" rel="noopener noreferrer" class="">properties</a> section of the message.</li>
<li class=""><strong>§ 4.2.5 application-properties filter</strong>: Applies to the immutable <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-application-properties" target="_blank" rel="noopener noreferrer" class="">application-properties</a> section of the message.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example">Example<a href="https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no">​</a></h2>
<p>Imagine each message carries metadata specifying a particular color.
Different consumers can subscribe to the same stream, filtering messages to receive only those matching the color they are interested in.</p>
<p></p><figure><img decoding="async" loading="lazy" alt="Consumers filtering messages from a stream" src="https://www.rabbitmq.com/assets/images/stream-filtering-consumers-cdb038faafdd400aa8bf6247996d5a82.svg" width="1074" height="572" class="img_ev3q"><figcaption>Consumers filtering messages from a stream</figcaption></figure><p></p>
<p>The first consumer receives all green messages.
The second consumer receives all purple messages.
The third consumer receives all blue messages.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>Try this example.</summary><div><div class="collapsibleContent_i85q"><p>You can try this example using the <a href="https://github.com/ansd/amqp-filter-expressions/tree/v0.1.0" target="_blank" rel="noopener noreferrer" class="">amqp-filter-expressions</a> sample app along with the <a href="https://github.com/rabbitmq/rabbitmq-amqp-java-client" target="_blank" rel="noopener noreferrer" class="">RabbitMQ AMQP 1.0 Java Client</a> by following these steps:</p><ol>
<li class="">Start the RabbitMQ server with the following command:</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> rabbitmq </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5672</span><span class="token plain">:5672 </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15672</span><span class="token plain">:15672 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    rabbitmq:4.1-rc-management</span><br></span></code></pre></div></div><ol start="2">
<li class="">Navigate to the root directory of the sample app and start the client:</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mvn clean compile exec:java</span><br></span></code></pre></div></div><p>Upon running the sample app, you should see the following output on the console:</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 0 with color green</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 1 with color blue</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 2 with color purple</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 3 with color purple</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 4 with color green</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher sent message 5 with color green</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter green) received message 0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter green) received message 4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter green) received message 5</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter purple) received message 2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter purple) received message 3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter blue) received message 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter &amp;s:e) received message 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter &amp;s:e) received message 2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">consumer (filter &amp;s:e) received message 3</span><br></span></code></pre></div></div><p>In this example, the publisher sends six messages, assigning each a specific color in the application-properties section.</p><ul>
<li class="">The first consumer applies an application-properties filter for <code>color: green</code>, receiving all green messages in the order they were published to the stream.</li>
<li class="">Similarly, the second consumer filters for <code>color: purple</code>, receiving all purple messages, and the third consumer filters for <code>color: blue</code>, receiving all blue messages.</li>
</ul><p>Additionally, this sample app contains a fourth consumer (not shown in the picture above) with a filter that matches messages whose color ends with the letter <code>e</code>.
(As per the specification, the filter expression <code>&amp;s:suffix</code> matches values ending with the specified suffix.)
This fourth consumer therefore receives messages with colors blue and purple.</p></div></div></details>
<p>AMQP filter expressions enable multiple clients to concurrently consume specific subsets of messages from the same stream while preserving message order.
This feature also minimizes network traffic between RabbitMQ and its clients by dispatching only the messages that match each client’s interests.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="stream-filtering-comparison">Stream Filtering Comparison<a href="https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions#stream-filtering-comparison" class="hash-link" aria-label="Direct link to Stream Filtering Comparison" title="Direct link to Stream Filtering Comparison" translate="no">​</a></h2>
<p>The <strong>AMQP filter expressions</strong> feature described in this blog post should not be confused with the <a class="" href="https://www.rabbitmq.com/blog/2023/10/16/stream-filtering"><strong>Bloom filter-based stream filtering</strong></a> introduced in RabbitMQ 3.13.</p>
<p>Both features serve the same purpose: filtering messages from a stream.
However, their implementations differ, resulting in distinct characteristics:</p>
<table><thead><tr><th>Feature</th><th>AMQP Filter Expressions</th><th>Bloom Filter Based-Stream Filtering</th></tr></thead><tbody><tr><td>Supported Protocols</td><td>AMQP 1.0</td><td>Primarily for the <a href="https://github.com/rabbitmq/rabbitmq-server/blob/main/deps/rabbitmq_stream/docs/PROTOCOL.adoc" target="_blank" rel="noopener noreferrer" class="">RabbitMQ Streams protocol</a>, but also supports AMQP 1.0, AMQP 0.9.1, and STOMP.</td></tr><tr><td>False Positives</td><td>None</td><td>Possible: Requires additional per-message filtering on the client side.</td></tr><tr><td>Support for Multiple Values to Filter on (Publisher)</td><td>Yes: Publishers can define multiple values in the properties or application-properties sections.</td><td>No: Publishers can assign only one filter value per message.</td></tr><tr><td>Support for Multiple Filter Expressions (Consumer)</td><td>Yes: Consumers can provide multiple filter expressions, and a message is delivered if <em>all</em> filters match.</td><td>Yes: Consumers can specify multiple filter values, and a message is delivered if <em>any</em> filter matches.</td></tr><tr><td>Prefix and Suffix Matching</td><td>Yes: For string values, consumers can define expressions like: "Filter messages whose <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-properties" target="_blank" rel="noopener noreferrer" class="">subject</a> starts with <code>emea.</code>" or "Filter messages whose <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-application-properties" target="_blank" rel="noopener noreferrer" class="">application-properties</a> section has a key <code>color</code> and the value ends with <code>e</code>.</td><td>No</td></tr><tr><td>Broker Overhead</td><td>Implemented using efficient Erlang pattern matching or term equality operations. However, every message is read into memory for each consumer (unless combined with Bloom filter-based filtering).</td><td>Minimal: Bloom filter membership checks use constant time.  With the RabbitMQ Streams protocol, the <a href="https://man7.org/linux/man-pages/man2/sendfile.2.html" target="_blank" rel="noopener noreferrer" class=""><code>sendfile</code> system call</a> optimizes chunk delivery without messages entering user space.</td></tr><tr><td>Network Overhead</td><td>Lower: Only messages matching the consumer's filters are transferred.</td><td>Higher: Entire <a class="" href="https://www.rabbitmq.com/blog/2023/10/24/stream-filtering-internals#structure-of-a-stream">chunks</a> are transferred even if only one message matches.</td></tr></tbody></table>
<p>Both features can be used together when consuming via AMQP 1.0.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://www.rabbitmq.com/blog/2024/12/13/amqp-filter-expressions#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>RabbitMQ 4.1 addresses the <a href="https://github.com/rabbitmq/rabbitmq-server/issues/262" target="_blank" rel="noopener noreferrer" class="">challenge</a> of enabling multiple consumers on a single queue/stream while ensuring certain messages (e.g., those with the same subject or ID) are always processed by the same consumer, preserving in-order processing.</p>
<p>Although this feature is not available for <a class="" href="https://www.rabbitmq.com/docs/classic-queues">classic queues</a> or <a class="" href="https://www.rabbitmq.com/docs/quorum-queues">quorum queues</a>, AMQP filter expressions allow consumers to filter messages when consuming from a stream.
Since streams are immutable logs, total message order is maintained.</p>]]></content:encoded>
            <category>AMQP 1.0</category>
            <category>Streams</category>
            <category>RabbitMQ 4.1</category>
            <category>New Features</category>
        </item>
    </channel>
</rss>