Why do RabbitMQ upgrades go wrong?
"A lot of times what companies struggle with, or they forget, is they don't do frequent upgrades. Sometimes it takes a couple years to do an upgrade. And if they try to go from where they are straight to the latest, they get a bunch of unforeseen issues — because what they should have done is upgrade step by step."
— Jeff Sogolov, AceMQ Engineer, Lucidya engagement session, May 2025
What is the required upgrade path from 3.x to 4.x?
rabbitmqctl enable_feature_flag allWhat about Erlang compatibility?
- 3.12 supports Erlang 25.x minimum
- 3.13 requires Erlang 26 minimum (26.2 recommended)
- 4.x also requires Erlang 26.2 minimum
"You can upgrade Erlang from 25 to 26.2 directly. Once you're on 26.2, you upgrade RabbitMQ to 3.13 — you already have the right Erlang. Then from 3.13 to 4.1, same Erlang version still applies."
— Jeff Sogolov, AceMQ Engineer, Lucidya session, May 2025
Strategy 1: Rolling Upgrade (In-Place)
- Stop node 1 (service only — not the OS)
- Upgrade Erlang on node 1 to the required version
- Upgrade RabbitMQ on node 1 to the target version
- Start the RabbitMQ service on node 1
- Confirm node 1 has rejoined the cluster and is healthy
- Repeat for nodes 2 and 3
Strategy 2: Blue-Green Deployment
- Provision a new cluster (green) on the target RabbitMQ and Erlang version
- Configure a federated queue upstream on the green cluster pointing to the blue cluster
- As consumers are moved to the green cluster, federation pulls messages from blue to green automatically
- Once all consumers are on green, move producers to green
- Once producers are moved, drain any remaining messages from blue using the shovel plugin
- Decommission the blue cluster
"Blue-green is zero downtime. You can do it at any time — there's no maintenance mode. The cost is that you have two clusters running at the same time, which some companies can't afford, especially on-prem. But for AWS-based deployments where you can spin up new clusters easily, it makes a lot of sense."
— Jeff Sogolov, AceMQ Engineer, Lucidya session, May 2025
Pre-upgrade checklist
- Confirm current RabbitMQ version and identify the required upgrade path
- Check the Erlang compatibility matrix for target and intermediate versions
- Enable all feature flags on the current version (rabbitmqctl enable_feature_flag all)
- Back up cluster definitions (topology, users, permissions) via Management API
- Validate staging environment upgrade end-to-end before touching production
- Confirm load balancer health check behavior with nodes taken offline
- Test client reconnect behavior in staging under simulated node restarts
- Schedule during lowest-traffic window if using rolling upgrade
- Have rollback plan documented before starting
For the wider readiness view before you commit to a window, see the RabbitMQ migration readiness checklist.
What changes in RabbitMQ 4.x that can break a 3.x estate
Most 3.x to 4.x upgrades that go wrong fail on one of a short list of changes. None of them are surprises if you read the 4.0 release notes, but each one is easy to miss in a large estate that grew up on 3.8 and 3.9 conventions.
Classic queue mirroring is gone. Mirrored classic queues (the ha-mode and ha-params policy keys) were deprecated in 3.9 and removed in 4.0. A 4.x node does not mirror classic queues, so any queue that relied on an HA policy for replication becomes a single-node queue the moment the policy stops applying. This is the one change that must be handled before the upgrade rather than after: migrate each mirrored queue to a quorum queue, then delete the HA policies. rabbitmq-diagnostics check_if_cluster_has_classic_queue_mirroring_policy tells you whether any remain. We cover the tradeoffs in our classic vs quorum queues post.
Transient non-exclusive queues are deprecated. Non-durable queues that are not exclusive to a connection are flagged as a deprecated feature and can be denied by configuration. They still work in 4.x, but plan on declaring durable queues everywhere and using exclusive queues for genuinely per-connection state.
The default queue type. Declaring a queue without x-queue-type still gives you a classic queue unless the virtual host sets default_queue_type. Set it to quorum per vhost for new workloads, and make sure client code that declares queues passes an explicit x-queue-type so nobody is surprised by a vhost-level default.
AMQP 1.0 is a core protocol. In 4.0 the separate AMQP 1.0 plugin is no longer needed; 1.0 is implemented natively alongside 0-9-1 on the same listener. Existing 0-9-1 clients are unaffected. Teams that were running the old plugin should remove it from their enabled plugins list, and teams that want 1.0 should move to the maintained 1.0 client libraries rather than legacy ones.
Khepri as the metadata store. Khepri, the Raft-based replacement for Mnesia, shipped as experimental in 3.13 and is supported in 4.x, but it is opt-in. Nodes keep using Mnesia after the upgrade until you deliberately enable the khepri_db feature flag. Treat that as a separate change with its own test window, not a side effect of the version bump.
Feature flags must all be enabled first. A 3.13 cluster with any stable feature flag still disabled cannot join a 4.x node, and the 4.x node refuses to start against it. Enable everything before the first node moves.
Plugins and the management UI. Plugins compiled for 3.x need 4.x builds. The management plugin itself carries forward, but it drops the mirroring views and the AMQP 1.0 plugin becomes a no-op. Audit any community plugin before assuming it works.
MQTT 5. MQTT 5 support arrived in 3.13 and carries into 4.x. If you are coming from 3.12 or older, your MQTT clients gain it as part of the path.
Erlang. 4.x requires Erlang/OTP 26 or later. If your nodes are still on OTP 25, the Erlang upgrade happens as part of the rolling upgrade, one node at a time. See our note on Erlang 26 end of life and RabbitMQ before you pick a target.
Should we stay on 3.13 or upgrade to 4.x?
3.13 is the last 3.x series. The community support window for it is short, and once it closes there are no upstream security patches for any 3.x version. That is the honest constraint that drives the decision.
Staying on 3.13 is reasonable in exactly one case: you have a commercial or extended support arrangement that backports security fixes to the version you are running. Without that, a 3.13 cluster is a CVE clock. Our extended LTS support covers 3.8.x through 3.13.x with backported patches, which is what lets clients run older series on a schedule they control rather than one dictated by the upstream calendar. It buys time; it does not remove the need to plan the move.
Upgrade when all four of these are true:
- Mirrored classic queues are gone and no HA policies remain.
- Every stable feature flag is enabled on every node.
- Erlang is on OTP 26 or later, or you are ready to move it during the rolling upgrade.
- Client applications are on maintained library versions that behave correctly against quorum queues (correct handling of
x-delivery-limit, dead lettering, and reconnect).
Upgrade sooner than your maintenance calendar suggests if you need AMQP 1.0 without the plugin, MQTT 5 on an older 3.x, or the 4.x quorum queue improvements, which include message priorities and a default delivery limit that stops poison messages from cycling forever.
If you are on 3.8 through 3.12, the answer is the same but the path is longer: get to 3.13 first, stabilise, then move to 4.x. We run both halves for clients and the upgrade service is scoped that way.
Whether staying is safe is a separate question from whether it is possible: is RabbitMQ 3.x still safe to run works through the end-of-life dates and the CVE exposure series by series. If you stay, extended LTS support for RabbitMQ 3.x keeps the version patched while the upgrade waits for a window.
The rolling upgrade runbook we use
This is the sequence we follow on client clusters. It assumes a three or five node cluster, quorum queues for anything that matters, and clients that reconnect on connection loss.
- Inventory. Record versions, Erlang versions, enabled plugins, and every policy. Run
rabbitmq-diagnostics check_if_any_deprecated_features_are_usedandrabbitmq-diagnostics check_if_cluster_has_classic_queue_mirroring_policyon any node. Both must come back clean before you continue. - Enable all stable feature flags.
rabbitmqctl enable_feature_flag allon one node applies cluster-wide. Confirm withrabbitmqctl list_feature_flags; anything stilldisabledblocks the upgrade. - Convert mirrored classic queues to quorum queues, flow by flow. Quorum queues cannot be converted in place. For each flow, declare the quorum queue, repoint consumers, repoint producers, drain the old queue, delete it. Do this per application so a mistake affects one flow, not the estate.
- Verify the Erlang target. Confirm the OTP 26 or later package is available on every node and that it is the version your 4.x build was tested against.
- Export definitions and take a backup.
rabbitmqctl export_definitionsplus a filesystem backup of the data directory on every node. The definitions export is what you rebuild from if the rollback boundary is crossed. - Upgrade one node at a time. Before stopping a node, run
rabbitmq-upgrade await_online_quorum_plus_oneso no quorum queue loses its majority while this node is out. Thenrabbitmq-upgrade drainputs the node in maintenance mode, closes client connections gracefully, and transfers quorum queue leadership away. Stop the service, upgrade Erlang if needed, upgrade RabbitMQ, start it, and confirm it rejoined. - Wait for quorum queue members to catch up.
rabbitmq-queues quorum_status <queue>on the busiest queues, orrabbitmq-diagnostics check_if_node_is_quorum_criticalon the next node you intend to stop. Do not start the next node until this passes. - Verify clients reconnected. Connection counts in the management UI should return to baseline on the upgraded node. If a client library does not reconnect, fix it now, before the next node.
- Repeat for each remaining node. The cluster runs mixed 3.13 and 4.x during this window. Do not change policies, add queues, or enable anything new until the last node is done.
- Enable the new 4.x feature flags. After the final node is upgraded,
rabbitmqctl enable_feature_flag allagain. This is the rollback boundary: once a 4.x-only feature flag is enabled there is no downgrade path. Everything before this step can be reversed by restoring a node to 3.13.
rabbitmqctl enable_feature_flag all
rabbitmq-upgrade await_online_quorum_plus_one
rabbitmq-upgrade drainBlue-green is the alternative when the cluster is small enough to rebuild, the definitions export is trustworthy, and you can afford to move clients by DNS or load balancer. It gives you a clean 4.x cluster and an intact 3.13 cluster to fall back to. We prefer it for clusters that have accumulated years of undocumented policies.
Either way, support covers the upgrade window with a 15-minute P1 response, which matters most between step 6 and step 10.
FAQ
Can I upgrade directly from RabbitMQ 3.13 to 4.x?
Yes. A rolling upgrade from 3.13.x to 4.0.x is supported, provided every stable feature flag is enabled, no classic queue mirroring policies remain, and Erlang is on OTP 26 or later. If you are on 3.12 or older you cannot skip to 4.x; upgrade to 3.13 first, enable its feature flags, then continue. The reason is that 4.x nodes only join clusters where the 3.13 feature flag set is fully enabled, and older series cannot satisfy that.
Can I stay on RabbitMQ 3.x?
You can, but only safely with a support arrangement that backports security fixes, because upstream patches for 3.x end with 3.13's community window. Our extended LTS support covers 3.8.x through 3.13.x with backported CVE patches for exactly this situation. Staying makes sense when a client migration, a compliance freeze, or a queue conversion needs more time than the upstream calendar allows. It does not make sense as a permanent state; plan the 4.x move on your own schedule.
How do you upgrade RabbitMQ without downtime?
Rolling upgrade, one node at a time. Enable all feature flags, remove mirrored classic queues, export definitions, then for each node run rabbitmq-upgrade await_online_quorum_plus_one, drain it, upgrade Erlang and RabbitMQ, restart, and wait for quorum queue members to catch up before touching the next node. Clients that reconnect on connection loss see a brief reconnect, not an outage. Blue-green, with a new 4.x cluster and a client cutover, is the option when the existing cluster is too tangled to upgrade in place.
Does RabbitMQ 4 require Erlang 26?
Yes. RabbitMQ 4.x requires Erlang/OTP 26 or later. If your 3.13 nodes are already on OTP 26 the Erlang step is a no-op; if they are on OTP 25, upgrade Erlang on each node during the same rolling window as the RabbitMQ package. Check the compatibility table for the exact 4.x patch release you are installing, since later 4.x releases raise the minimum. Our post on Erlang 26 end of life covers what that means for support timelines.