PageSourceSearch

https://www.rabbitmq.com/assets/js/08cbbdd9.a937b2c5.js

js rabbitmq.com collected 2026-09-24 06:05:12 UTC 35,104 bytes, 2 lines download raw bytes

1"use strict";(self.webpackChunkrabbitmq_website=self.webpackChunkrabbitmq_website||[]).push([["13612"],{84784(e,n,r){r.r(n),r.d(n,{metadata:()=>t,default:()=>p,frontMatter:()=>o,contentTitle:()=>d,toc:()=>h,assets:()=>c});var t=JSON.parse('{"id":"upgrade","title":"Upgrading RabbitMQ","description":"\x3c!--","source":"@site/versioned_docs/version-4.1/upgrade.md","sourceDirName":".","slug":"/upgrade","permalink":"/docs/4.1/upgrade","draft":false,"unlisted":false,"editUrl":"https://github.com/rabbitmq/rabbitmq-website/tree/main/versioned_docs/version-4.1/upgrade.md","tags":[],"version":"4.1","frontMatter":{"title":"Upgrading RabbitMQ"},"sidebar":"docsSidebar","previous":{"title":"Kubernetes (Do It Yourself)","permalink":"/docs/4.1/install-kubernetes-diy"},"next":{"title":"Rolling Upgrade","permalink":"/docs/4.1/rolling-upgrade"}}'),i=r(74848),a=r(28453),s=r(50773),l=r(57250);let o={title:"Upgrading RabbitMQ"},d="Upgrading RabbitMQ",c={},h=[{value:"Upgrade Strategies",id:"strategies",level:2},{value:"Rolling (in-place) Upgrade",id:"rolling-upgrade",level:3},{value:"Blue-Green Deployment",id:"blue-green-deployment",level:3},{value:"Grow-then-Shrink Upgrade",id:"grow-then-shrink-upgrade",level:3},{value:"RabbitMQ Version Upgradability",id:"rabbitmq-version-upgradability",level:2},{value:"Erlang Version Requirements",id:"rabbitmq-erlang-version-requirement",level:2},{value:"Plugin Compatibility Between Versions",id:"rabbitmq-plugins-compatibility",level:2},{value:"Management Plugin Upgrades",id:"management-ui",level:3},{value:"Upgrade Considerations",id:"upgrade-considerations",level:2},{value:"Changes in System Resource Usage",id:"system-resource-usage",level:3},{value:"Upgrading a Single Node Installation",id:"single-node-upgrade",level:3},{value:"Upgrading Development Environments",id:"upgrading-dev-environments",level:4},{value:"Downgrades",id:"downgrades",level:3},{value:"Backup",id:"backup",level:3},{value:"When to Restart Nodes",id:"maintaining-quorum",level:3},{value:"Rebalancing Queue Leaders",id:"rebalance",level:3},{value:"Full-Stop Upgrades",id:"full-stop-upgrades",level:3},{value:"Maintenance Mode",id:"maintenance-mode",level:2},{value:"Enabling Maintenance Mode",id:"enabling-maintenance-mode",level:3},{value:"Disabling Maintenance Mode",id:"disabling-maintenance-mode",level:3},{value:"Checking Maintenance Status",id:"checking-maintenance-status",level:3},{value:"Handling Node Restarts in Applications",id:"rabbitmq-restart-handling",level:2}];function u(e){let n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.R)(),...e.components},{Details:r}=n;return r||function(e,n){throw Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"upgrading-rabbitmq",children:"Upgrading RabbitMQ"})}),"\n",(0,i.jsx)(n.h2,{id:"strategies",children:"Upgrade Strategies"}),"\n",(0,i.jsx)(n.p,{children:"There are three major upgrade strategies that can be used with RabbitMQ. Below you'll find a brief overview\nof all of them. Each strategy has a dedicated page with more detailed information."}),"\n",(0,i.jsx)(n.h3,{id:"rolling-upgrade",children:"Rolling (in-place) Upgrade"}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"This upgrade strategy is recommended"})}),"\n",(0,i.jsxs)(n.p,{children:["A rolling upgrade (also referred to as in-place upgrade) is an upgrade process where nodes are upgraded one by one.\nRefer to the ",(0,i.jsx)(n.a,{href:"./rolling-upgrade",children:"rolling upgrade guide"})," page for more details, but here are the main steps:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Investigate if the current and target versions have a rolling upgrade path","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"#rabbitmq-version-upgradability",children:"version upgradability"})]}),"\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"#rabbitmq-erlang-version-requirement",children:"Erlang version requirements"})]}),"\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.0",children:"the release notes"})]}),"\n",(0,i.jsxs)(n.li,{children:["verify that all ",(0,i.jsx)(n.a,{href:"./feature-flags#how-to-enable-feature-flags",children:"stable feature flags are enabled"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Check that the node or cluster is in a good state in order to be upgraded","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["no ",(0,i.jsx)(n.a,{href:"./alarms",children:"alarms"})," are in effect"]}),"\n",(0,i.jsx)(n.li,{children:"no ongoing queue or stream replica sync operations"}),"\n",(0,i.jsx)(n.li,{children:"the system is otherwise under a reasonable load"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["For each node","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"stop the node"}),"\n",(0,i.jsx)(n.li,{children:"upgrade RabbitMQ and, if applicable, Erlang"}),"\n",(0,i.jsx)(n.li,{children:"start the node"}),"\n",(0,i.jsxs)(n.li,{children:["watch ",(0,i.jsx)(n.a,{href:"./monitoring",children:"monitoring and health check"})," data to assess the health and recovery of the upgraded node and cluster"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Once all nodes are upgraded, ",(0,i.jsx)(n.a,{href:"./feature-flags#how-to-enable-feature-flags",children:"enable stable feature flags"})," introduced in the new version"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"blue-green-deployment",children:"Blue-Green Deployment"}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"This upgrade strategy is the safest option. It is recommended\nfor environments where a rolling upgrade is not an option\nfor any reason, or extra safety is particularly important"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"./blue-green-upgrade",children:"The Blue/Green deployment"})," strategy offers the benefit of making the upgrade process safer at the cost of\ntemporary increasing infrastru
1cture footprint. The safety aspect comes from the fact that the operator\ncan abort an upgrade by switching applications back to the old cluster."]}),"\n",(0,i.jsxs)(n.p,{children:["A blue-green upgrade usually involves the following steps performed by a deployment tool or manually\nby an operator. Refer to the ",(0,i.jsx)(n.a,{href:"./blue-green-upgrade",children:"blue-green deployment guide"})," for more details about these steps:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Deploy a new cluster with the desired version"}),"\n",(0,i.jsx)(n.li,{children:"Synchronize metadata between the old and the new cluster (unless applications can declare their own metadata)"}),"\n",(0,i.jsx)(n.li,{children:"Set up federation"}),"\n",(0,i.jsx)(n.li,{children:"Switch consumers to the new cluster"}),"\n",(0,i.jsx)(n.li,{children:"Drain messages"}),"\n",(0,i.jsx)(n.li,{children:"Switch publishers to the new cluster"}),"\n",(0,i.jsx)(n.li,{children:"Decommission the old cluster"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"There's also a simplfied version of the blue-green strategy, if some downtime is acceptable:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Deploy a new cluster with the target version"}),"\n",(0,i.jsx)(n.li,{children:"Stop the applications"}),"\n",(0,i.jsx)(n.li,{children:"Synchronize metadata between the old and new clusters"}),"\n",(0,i.jsxs)(n.li,{children:["Move all messages from the old cluster to the new one (e.g. using ",(0,i.jsx)(n.a,{href:"./shovel",children:"Shovel"}),")"]}),"\n",(0,i.jsx)(n.li,{children:"Reconfigure applications to use the new cluster"}),"\n",(0,i.jsx)(n.li,{children:"Start publishers and consumers"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"grow-then-shrink-upgrade",children:"Grow-then-Shrink Upgrade"}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsxs)(n.p,{children:["This upgrade strategy changes replica identities, can result in massive\nunnecessary data transfers between nodes, and is only safe with important\nprecautions. Therefore, it is ",(0,i.jsx)(n.strong,{children:"highly recommended against"})," for cluster-wide upgrades."]})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"This strategy, however, can be a reasonable choice for replacing a single cluster node."})}),"\n",(0,i.jsx)(n.p,{children:"A grow-and-shrink upgrade usually involves the\nfollowing steps. Consider a three node cluster with nodes A, B, and C:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Investigate if the current and target versions can be clustered together","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"#rabbitmq-version-upgradability",children:"version upgradability"}),"; if a rolling upgrade between the old and new version is not supported,\nthat also means that these two versions cannot coexist in a single cluster"]}),"\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"#rabbitmq-erlang-version-requirement",children:"Erlang version requirements"})]}),"\n",(0,i.jsxs)(n.li,{children:["check ",(0,i.jsx)(n.a,{href:"https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.0.0",children:"the release notes"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Add a new node, node D, to the cluster\nfor node D to be able to join the cluster)"}),"\n",(0,i.jsx)(n.li,{children:"Place a new replica of every quorum queue and every stream on the new node"}),"\n",(0,i.jsxs)(n.li,{children:["Check that the node or cluster is in a good state","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["no ",(0,i.jsx)(n.a,{href:"./alarms",children:"alarms"})," are in effect"]}),"\n",(0,i.jsx)(n.li,{children:"no ongoing queue or stream replica sync operations"}),"\n",(0,i.jsx)(n.li,{children:"the system is otherwise under a reasonable load"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Remove node A from the cluster using ",(0,i.jsx)(n.code,{children:"rabbitmqctl forget_cluster_node"})]}),"\n",(0,i.jsx)(n.li,{children:"Repeat the steps above for the other nodes; in a 3-node cluster example, the cluster should now consist of nodes D, E and F"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"./feature-flags#how-to-enable-feature-flags",children:"Enable stable feature flags"})," introduced in the new version"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This strategy is only recommended for replacing one node that must be decomissioned, not upgrading multiple nodes."}),"\n",(0,i.jsx)(n.h2,{id:"rabbitmq-version-upgradability",children:"RabbitMQ Version Upgradability"}),"\n",(0,i.jsx)(n.p,{children:"It is possible to upgrade RabbitMQ 3.13.x directly to version up to RabbitMQ 4.1.x."}),"\n",(0,i.jsxs)(n.p,{children:["All ",(0,i.jsx)(n.a,{href:"./feature-flags#how-to-enable-feature-flags",children:"stable feature flags must be enabled"}),",\n",(0,i.jsx)(n.strong,{children:"before"})," an upgrade, or the upgrade may fail."]}),"\n",(0,i.jsx)(n.p,{children:"If you are not on RabbitMQ 3.13 yet, refer to the table below to understand your upgrade path."}),"\n",(0,i.jsxs)(r,{children:[(0,i.jsx)("summary",{children:"Release Series Upgradeability"}),(0,i.jsx)(n.p,{children:"The following shows the supported upgrade paths."}),(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"From"}),(0,i.jsx)(n.th,{children:"To"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"4.1.x"}),(0,i.jsx)(n.td,{children:"4.2.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"4.0.x"}),(0,i.jsx)(n.td,{children:"4.2.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"4.0.x"}),(0,i.jsx)(n.td,{children:"4.1.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.13.x"}),(0,i.jsx)(n.td,{children:"4.2.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.13.x"}),(0,i.jsx)(n.td,{children:"4.1.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.13.x"}),(0,i.jsx)(n.td,{children:"4.0.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.12.x"}),(0,i.jsx)(n.td,{children:"3.13.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.11.18"}),(0,i.jsx)(n.td,{children:"3.12.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.10.x"}),(0,i.jsx)(n.td,{children:"3.11.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.9.x"}),(0,i.jsx)(n.td,{children:"3.10.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.8.x"}),(0,i.jsx)(n.td,{children:"3.9.x"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"3.7.18"}),(0,i.jsx)(n.td,{children:"3.8.x"})]})]})]})]}),"\n",(0,i.jsx)(n.admonition,{type:"note",children:(0,i.jsxs)(n.p,{children:["RabbitMQ 3.13 included experimental support for Khepri. However, major changes\nhad to be introduced since then, leading to incompatibilities between Khepri support\nin 3.13 and 4.x. Therefore, RabbitMQ 3.13 with Khepri enabled ",(0,i.jsx)(n.strong,{children:"cannot"})," be upgraded\nto 4.x. ",(0,i.jsx)(n.a,{href:"./blue-green-upgrade",children:"Blue-Green Deployment"})," can still be used in this situation,\nsince technically it is not an upgrade, but rather a migration to a fresh cluster."]})}),"\n",(0,i.jsx)(n.h2,{id:"rabbitmq-erlang-version-requirement",children:"Erlang Version Requirements"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to the ",(0,i.jsx)(n.a,{href:"./which-erlang",children:"Erlang Version Requirements"})," guide\nto learn the minimum required and maximum supported version of Erlang for a given RabbitMQ version."]}),"\n",(0,i.jsx)(n.p,{children:"It's generally recommended to use the latest Erlang version supported by the target RabbitMQ version."}),"\n",(0,i.jsx)(n.p,{children:"We recommend that you upgrade Erlang together with RabbitMQ."}),"\n",(0,i.jsx)(n.h2,{id:"rabbitmq-plugins-compatibility",children:"Plugin Compatibility Between Versions"}),"\n",(0,i.jsxs)(n.p,{children:["Plugins included in the RabbitMQ distribution are guaranteed to be compatible with the\nversion they are distributed with. If ",(0,i.jsx)(n.a,{href:"/community-plugins",children:"community plugins"})," are used,\nthey need to be verified separately."]}),"\n",(0,i.jsx)(n.h3,{id:"management-ui",children:"Management Plugin Upgrades"}),"\n",(0,i.jsx)(n.p,{children:"RabbitMQ management plugin comes with a Web application that runs in the browser."}),"\n",(0,i.jsx)(n.p,{children:"After upgrading a cluster, it is highly recommended to clear browser cache,\nlocal storage, session storage and cookies for the domain(s) used to access the management UI.\nOtherwise, you may experience JavaScript errors."}),"\n",(0,i.jsx)(n.h2,{id:"upgrade-considerations",children:"Upgrade Considerations"}),"\n",(0,i.jsx)(n.h3,{id:"system-resource-usage",children:"Changes in System Resource Usage"}),"\n",(0,i.jsx)(n.p,{children:"During and after the upgrade, connections and queues will be balanced\ndifferently between the nodes: as nodes go down, connections\nwill be reestablished on the remaining nodes and queue leaders will be reelected.\nIt is important to make sure your cluster can sustain the workload while some,\nusually one, node is down for the upgrade. Performing the upgrade during low\ntraffic hours is recommended."}),"\n",(0,i.jsx)(n.p,{children:"Additionally, different versions of RabbitMQ can have different resource usage. That\nshould be taken into account before upgrading: make sure there's enough\ncapacity to run the workload with the new version. Always consult with\nthe release notes of all versions between the one currently deployed and the\ntarget one in order to find out about changes which could impact\nyour workload and resource usage."}),"\n",(0,i.jsx)(n.h3,{id:"single-node-upgrade",children:"Upgrading a Single Node Installation"}),"\n",(0,i.jsx)(n.p,{children:"There are no fundamental differences between upgrading a single node installation compared\nto upgrading a multi-node cluster."}),"\n",(0,i.jsx)(n.h4,{id:"upgrading-dev-environments",children:"Upgrading Development Environments"}),"\n",(0,i.jsx)(n.p,{children:"Single node deployments are often local development or test environments. In such cases, if\nthe messages stored in RabbitMQ are not important, it may be easier to simply\ndelete everything in the data directory and start a fresh n
1ode of the new version. Effectively,\nit's no longer an upgrade but a fresh installation of the new version."}),"\n",(0,i.jsxs)(n.p,{children:["Please note that this process will ",(0,i.jsx)(n.strong,{children:"delete all data"})," in your RabbitMQ (definitions and messages), but this is usually\nnot a problem in a development/test environment. The definitions can be preserved using ",(0,i.jsx)(n.a,{href:"./definitions",children:"export/import"}),".\nThe benefit of this approach is that you can easily jump from any version to any other version without worrying\nabout compatibility and feature flags."]}),"\n",(0,i.jsx)(n.h3,{id:"downgrades",children:"Downgrades"}),"\n",(0,i.jsxs)(n.p,{children:["RabbitMQ does not officially support downgrades - they are not tested and should not be relied upon.\nUsers who want extra safety can use ",(0,i.jsx)(n.a,{href:"./blue-green-upgrade",children:"blue-green deployment"})," approach,\nwhich allows switching back to the old environment."]}),"\n",(0,i.jsx)(n.p,{children:"Having said that, downgrades technically work between some versions, especially if they only differ by a patch release.\nIt is not guaranteed however: there have been patch releases that could not be downgraded even to the immediately\npreceding patch release."}),"\n",(0,i.jsx)(n.h3,{id:"backup",children:"Backup"}),"\n",(0,i.jsx)(n.p,{children:"It's strongly advised to back node's data directory up before upgrading."}),"\n",(0,i.jsx)(n.h3,{id:"maintaining-quorum",children:"When to Restart Nodes"}),"\n",(0,i.jsx)(n.p,{children:"Multiple components and features depend on the availability of a quorum of nodes. In the most common\ncase of a 3-node cluster, this means that 2 nodes should always be available during the upgrade."}),"\n",(0,i.jsxs)(n.p,{children:["RabbitMQ provides a ",(0,i.jsx)(n.a,{href:"./monitoring#health-checks",children:"health check"})," command that would fail\nshould any quorum queues, stream queues or other internal components on the target node lose their quorum, if that node was to be shut down:"]}),"\n",(0,i.jsxs)(s.A,{groupId:"examples",children:[(0,i.jsx)(l.A,{value:"bash",label:"bash",default:!0,children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# exits with a non-zero code if any of the internal components, quorum queues or stream queues\n# will lose online quorum should the target node be shut down;\n# additionally, it will print which components and/or queues are affected\nrabbitmq-diagnostics check_if_node_is_quorum_critical\n"})})}),(0,i.jsx)(l.A,{value:"PowerShell",label:"PowerShell",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-PowerShell",children:"# exits with a non-zero code if any of the internal components, quorum queues or stream queues\n# will lose online quorum should the target node be shut down;\n# additionally, it will print which components and/or queues are affected\nrabbitmq-diagnostics.bat check_if_node_is_quorum_critical\n"})})})]}),"\n",(0,i.jsx)(n.p,{children:"For example, consider a three node cluster with nodes A, B, and C and some quorum queues. If node B is currently down,\nthis check will fail if executed against node A or C, because if A or C went down, there would only be one node running\n(and therefore, there would be no quorum). When node B comes back online, the same check would succeed."}),"\n",(0,i.jsxs)(n.p,{children:["When automating the upgrade process, you can use ",(0,i.jsx)(n.code,{children:"rabbitmq-upgrade await_online_quorum_plus_one"})," command\nto block the node shutdown process until there is enough nodes running to maintain quorum. Note that\nsome deployment options already incorporate this check - for example, when running RabbitMQ on Kubernetes\nusing the ",(0,i.jsx)(n.a,{href:"/kubernetes/operator/operator-overview",children:"Cluster Operator"}),", this is already a part of the ",(0,i.jsx)(n.code,{children:"preStop"})," hook."]}),"\n",(0,i.jsx)(n.h3,{id:"rebalance",children:"Rebalancing Queue Leaders"}),"\n",(0,i.jsx)(n.p,{children:"If either the rolling or grown-then-shrink upgrade strategy is used, queue leaders will not be evenly distributed\nbetween the nodes after the upgrade. Rebalancing of queue and stream leaders helps spread the load across all cluster nodes."}),"\n",(0,i.jsx)(n.p,{children:"To rebalance all queue and stream leader replicas, run:"}),"\n",(0,i.jsxs)(s.A,{groupId:"examples",children:[(0,i.jsx)(l.A,{value:"bash",label:"bash",default:!0,children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"rabbitmq-queues rebalance all\n"})})}),(0,i.jsx)(l.A,{value:"PowerShell",label:"PowerShell",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-PowerShell",children:"rabbitmq-queues.bat rebalance all\n"})})})]}),"\n",(0,i.jsx)(n.h3,{id:"full-stop-upgrades",children:"Full-Stop Upgrades"}),"\n",(0,i.jsx)(n.p,{children:"There is no need to stop all nodes in a cluster to perform an upgrade."}),"\n",(0,i.jsx)(n.h2,{id:"maintenance-mode",children:"Maintenance Mode"}),"\n",(0,i.jsx)(n.p,{children:"Maintenance mode is a special node operation mode that can be useful during upgrades.\nThe mode is explicitly turned on and off by the operator using a bunch of new CLI commands covered below."}),"\n",(0,i.jsxs)(n.p,{children:["When a node is in maintenance mode, it ",(0,i.jsx)(n.strong,{children:"will not be available for serving client traffic"}),"\nand will try to transfer as many of its responsibilities as practically possible and safe."]}),"\n",(0,i.jsx)(n.p,{children:"Currently this involves the following steps:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Suspend all client connection listeners (no new client connections will be accepted)"}),"\n",(0,i.jsx)(n.li,{children:"Close all existing client connections: applications are expected to reconnect to other nodes and recover"}),"\n",(0,i.jsx)(n.li,{children:"Transfer primary replicas of all quorum queues hosted on the target node, and prevent them from participating\nin the subsequently triggered Raft elections"}),"\n",(0,i.jsx)(n.li,{children:"Mark the node as down for maintenance"}),"\n",(0,i.jsx)(n.li,{children:"At this point, a node shutdown will be least disruptive as the node has already transferred most of its\nresponsibilities"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"A node in maintenance mode will not be considered for new primary queue replica placement, regardless\nof queue type and whether the queue type supports replication."}),"\n",(0,i.jsx)(n.p,{children:"This feature is expected to evolve based on the feedback from RabbitMQ operators, users,\nand RabbitMQ core team's own experience with it."}),"\n",(0,i.jsx)(n.p,{children:"A node in maintenance mode is expected to be shut down, upgraded or reconfigured, and restarted in a short\ntime window (say, 5-30 minutes). Nodes are not expected to be running in this mode permanently or\nfor long periods of time."}),"\n",(0,i.jsx)(n.h3,{id:"enabling-maintenance-mode",children:"Enabling Maintenance Mode"}),"\n",(0,i.jsxs)(n.p,{children:["To put a node into maintenance, use ",(0,i.jsx)(n.code,{children:"rabbitmq-upgrade drain"}),":"]}),"\n",(0,i.jsxs)(s.A,{groupId:"examples",children:[(0,i.jsx)(l.A,{value:"bash",label:"bash",default:!0,children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"rabbitmq-upgrade drain\n"})})}),(0,i.jsx)(l.A,{value:"PowerShell",label:"PowerShell",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-PowerShell",children:"rabbitmq-upgrade.bat drain\n"})})})]}),"\n",(0,i.jsx)(n.h3,{id:"disabling-maintenance-mode",children:"Disabling Maintenance Mode"}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"A restart takes the node out of maintenance mode automatically."})}),"\n",(0,i.jsxs)(n.p,{children:["A node in maintenance mode can be ",(0,i.jsx)(n.em,{children:"revived"}),", that is, ",(0,i.jsx)(n.strong,{children:"brought back into its regular operational state"}),",\nusing ",(0,i.jsx)(n.code,{children:"rabbitmq-upgrade revive"}),":"]}),"\n",(0,i.jsxs)(s.A,{groupId:"examples",children:[(0,i.jsx)(l.A,{value:"bash",label:"bash",default:!0,children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"rabbitmq-upgrade revive\n"})})}),(0,i.jsx)(l.A,{value:"PowerShell",label:"PowerShell",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-PowerShell",children:"rabbitmq-upgrade.bat revive\n"})})})]}),"\n",(0,i.jsxs)(n.p,{children:["The command exists to roll back (to the extent possible) the effects of the ",(0,i.jsx)(n.code,{children:"drain"})," command.\nIt is only necessary to run this command if you decided you can't restart the node as planned."]}),"\n",(0,i.jsxs)(n.p,{children:["It is ",(0,i.jsx)(n.strong,{children:"not"})," necessary to revive a node after it was restarted/upgraded, because the restart\nautomatically takes the node out of maintenance mode."]}),"\n",(0,i.jsx)(n.h3,{id:"checking-maintenance-status",children:"Checking Maintenance Status"}),"\n",(0,i.jsxs)(n.p,{children:["You can check whether any of the nodes in the cluster is in the maintenance mode\nby running ",(0,i.jsx)(n.code,{children:"rabbitmqctl cluster_status"}),". You can also check the status of a specific\nnode by running ",(0,i.jsx)(n.code,{children:"rabbitmqctl status"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"rabbitmq-restart-handling",children:"Handling Node Restarts in Applications"}),"\n",(0,i.jsx)(n.p,{children:"In order to reduce or eliminate the downtime, applications (both producers\nand consumers) should be able to cope with a server-initiated connection\nclose. Some client libraries offer automatic connection recovery\nto help with this:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/client-libraries/java-api-guide#recovery",children:"Java client"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/client-libraries/dotnet-api-guide#connection-recovery",children:".NET client"})}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"http://rubybunny.info/articles/error_handling.html#network_connection_failures",children:"Bunny"})," (Ruby)"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"In most client libraries there is a way to react to a connection closure, for example:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://pika.readthedocs.io/en/stable/modules/connection.html#pika.c
1onnection.Connection.add_on_close_callback",children:"Pika"})," (Python)"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/rabbitmq/amqp091-go#Connection.NotifyClose",children:"Go"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The recovery procedure for many applications follows the same steps:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Reconnect"}),"\n",(0,i.jsx)(n.li,{children:"Re-open channels"}),"\n",(0,i.jsxs)(n.li,{children:["Restore channel settings (e.g. the ",(0,i.jsxs)(n.a,{href:"./confirms",children:[(0,i.jsx)(n.code,{children:"basic.qos"})," setting"]}),", publisher confirms)"]}),"\n",(0,i.jsx)(n.li,{children:"Recover topology"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Topology recovery includes the following actions, performed for every channel:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Re-declare exchanges declared by the application"}),"\n",(0,i.jsx)(n.li,{children:"Re-declare queues"}),"\n",(0,i.jsxs)(n.li,{children:["Recover bindings (both queue and ",(0,i.jsx)(n.a,{href:"./e2e",children:"exchange-to-exchange"})," ones)"]}),"\n",(0,i.jsx)(n.li,{children:"Recover consumers"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This algorithm covers the majority of use cases and is what the\naforementioned automatic recovery feature implements."}),"\n",(0,i.jsxs)(n.p,{children:["During a rolling upgrade when a node is stopped, clients connected to this node\nwill be disconnected using a server-sent ",(0,i.jsx)(n.code,{children:"connection.close"})," method and should reconnect to a different node.\nThis can be achieved by using a load balancer or proxy in front of the cluster\nor by specifying multiple server hosts if client library supports this feature."]}),"\n",(0,i.jsx)(n.p,{children:"Many client libraries libraries support host lists, for example:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://rabbitmq.github.io/rabbitmq-java-client/api/current/com/rabbitmq/client/ConnectionFactory.html#newConnection%28com.rabbitmq.client.Address%5B%5D%29",children:"Java client"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/rabbitmq/rabbitmq-dotnet-client/blob/main/projects/RabbitMQ.Client/client/api/ConnectionFactory.cs#L392",children:".NET client"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"http://api.rubybunny.info/Bunny/Session.html#constructor_details",children:"Bunny"})}),"\n"]})]})}function p(e={}){let{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},57250(e,n,r){r.d(n,{A:()=>l});var t=r(74848);r(96540);var i=r(34164),a=r(57663);function s({children:e,className:n,hidden:r}){return(0,t.jsx)("div",{role:"tabpanel",className:(0,i.A)("tabItem_Ymn6",n),hidden:r,children:e})}function l({children:e,className:n,value:r}){let{selectedValue:i,lazy:o}=(0,a.uc)(),d=r===i;return!d&&o?null:(0,t.jsx)(s,{className:n,hidden:!d,children:e})}},50773(e,n,r){r.d(n,{A:()=>u});var t=r(74848);r(96540);var i=r(34164),a=r(88287),s=r(57663),l=r(28584),o=r(19863);function d({className:e}){let{selectedValue:n,selectValue:r,tabValues:a,block:o}=(0,s.uc)(),c=[],{blockElementScrollPositionUntilNextRender:h}=(0,l.a_)(),u=e=>{let t=e.currentTarget,i=a[c.indexOf(t)].value;i!==n&&(h(t),r(i))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{let r=c.indexOf(e.currentTarget)+1;n=c[r]??c[0];break}case"ArrowLeft":{let r=c.indexOf(e.currentTarget)-1;n=c[r]??c[c.length-1]}}n?.focus()};return(0,t.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.A)("tabs",{"tabs--block":o},e),children:a.map(({value:e,label:r,attributes:a})=>(0,t.jsx)("li",{role:"tab",tabIndex:n===e?0:-1,"aria-selected":n===e,ref:e=>{c.push(e)},onKeyDown:p,onClick:u,...a,className:(0,i.A)("tabs__item","tabItem_LNqP",a?.className,{"tabs__item--active":n===e}),children:r??e},e))})}function c({children:e}){return(0,t.jsx)("div",{className:"margin-top--md",children:e})}function h({className:e,children:n}){return(0,t.jsxs)("div",{className:(0,i.A)(a.G.tabs.container,"tabs-container","tabList__CuJ"),children:[(0,t.jsx)(d,{className:e}),(0,t.jsx)(c,{children:n})]})}function u(e){let n=(0,o.A)(),r=(0,s.OC)(e);return(0,t.jsx)(s.O_,{value:r,children:(0,t.jsx)(h,{className:e.className,children:(0,s.vT)(e.children)})},String(n))}},57663(e,n,r){r.d(n,{OC:()=>u,O_:()=>b,uc:()=>g,vT:()=>c});var t=r(74848),i=r(96540),a=r(56347),s=r(99989),l=r(96629),o=r(80618),d=r(41367);function c(e){return i.Children.toArray(e).filter(e=>"\n"!==e)}function h({value:e,tabValues:n}){return n.some(n=>n.value===e)}function u(e){let n,{defaultValue:r,queryString:t=!1,groupId:c}=e,u=function(e){let{values:n,children:r}=e;return(0,i.useMemo)(()=>{let e=n??i.Children.toArray(r).flatMap(e=>{if(!e)return[];if((0,i.isValidElement)(e)&&function(e){let{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return[e];
1let n="string"==typeof e.type?e.type:e.type.name;throw Error(`Docusaurus error: Bad <Tabs> child <${n}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.
2If you do not want to pass on a "value" prop to the direct children of <Tabs>, you can also pass an explicit <Tabs values={...}> prop.`)}).map(({props:{value:e,label:n,attributes:r,default:t}})=>({value:e,label:n,attributes:r,default:t})),t=(0,o.XI)(e,(e,n)=>e.value===n.value);if(t.length>0)throw Error(`Docusaurus error: Duplicate values "${t.map(e=>`'${e.value}'`).join(", ")}" found in <Tabs>. Every value needs to be unique.`);return e},[n,r])}(e),[p,g]=(0,i.useState)(()=>(function({defaultValue:e,tabValues:n}){if(0===n.length)throw Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(e){if(!h({value:e,tabValues:n}))throw Error(`Docusaurus error: The <Tabs> has a defaultValue "${e}" but none of its children has the corresponding value. Available values are: ${n.map(e=>e.value).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return e}let r=n.find(e=>e.default)??n[0];if(!r)throw Error("Unexpected error: 0 tabValues");return r.value})({defaultValue:r,tabValues:u})),[b,m]=function({queryString:e=!1,groupId:n}){let r=(0,a.W6)(),t=function({queryString:e=!1,groupId:n}){if("string"==typeof e)return e;if(!1===e)return null;if(!0===e&&!n)throw Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:e,groupId:n});return[(0,l.aZ)(t),(0,i.useCallback)(e=>{if(!t)return;let n=new URLSearchParams(r.location.search);n.set(t,e),r.replace({...r.location,search:n.toString()})},[t,r])]}({queryString:t,groupId:c}),[x,f]=function({groupId:e}){let n=e?`docusaurus.tab.${e}`:null,[r,t]=(0,d.Dv)(n);return[r,(0,i.useCallback)(e=>{n&&t.set(e)},[n,t])]}({groupId:c}),j=h({value:n=b??x,tabValues:u})?n:null;return(0,s.A)(()=>{j&&g(j)},[j]),{selectedValue:p,selectValue:(0,i.useCallback)(e=>{if(!h({value:e,tabValues:u}))throw Error(`Can't select invalid tab value=${e}`);g(e),m(e),f(e)},[m,f,u]),tabValues:u,lazy:e.lazy??!1,block:e.block??!1}}let p=(0,i.createContext)(null);function g(){let e=i.useContext(p);if(!e)throw Error("useTabsContext() must be used within a Tabs component");return e}function b(e){return(0,t.jsx)(p.Provider,{value:e.value,children:e.children})}},28453(e,n,r){r.d(n,{R:()=>s,x:()=>l});var t=r(96540);let i={},a=t.createContext(i);function s(e){let n=t.useContext(a);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.