PageSourceSearch

https://www.rabbitmq.com/assets/js/44bb9a75.89febd4c.js

js rabbitmq.com collected 2026-09-24 06:05:23 UTC 15,507 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkrabbitmq_website=self.webpackChunkrabbitmq_website||[]).push([["14694"],{98453(e,s,n){n.r(s),n.d(s,{metadata:()=>i,default:()=>d,frontMatter:()=>r,contentTitle:()=>o,toc:()=>u,assets:()=>l});var i=JSON.parse('{"id":"classic-queues","title":"Classic Queues","description":"\x3c!--","source":"@site/versioned_docs/version-4.1/classic-queues.md","sourceDirName":".","slug":"/classic-queues","permalink":"/docs/4.1/classic-queues","draft":false,"unlisted":false,"editUrl":"https://github.com/rabbitmq/rabbitmq-website/tree/main/versioned_docs/version-4.1/classic-queues.md","tags":[],"version":"4.1","frontMatter":{"title":"Classic Queues","displayed_sidebar":"docsSidebar"},"sidebar":"docsSidebar","previous":{"title":"Quorum Queues","permalink":"/docs/4.1/quorum-queues/"},"next":{"title":"Time-to-Live and Expiration","permalink":"/docs/4.1/ttl"}}'),t=n(74848),a=n(28453);let r={title:"Classic Queues",displayed_sidebar:"docsSidebar"},o="Classic Queues",l={},u=[{value:"What is a Classic Queue",id:"overview",level:2},{value:"Classic Queue Features",id:"features",level:2},{value:"Persistence (Durable Storage) in Classic Queues",id:"persistence",level:2},{value:"Classic Queue Storage Implementation Versions",id:"versions",level:2},{value:"Classic Queue Implementation Version 1",id:"classic-queue-implementation-version-1",level:4},{value:"Classic Queue Implementation Version 2",id:"classic-queue-implementation-version-2",level:3},{value:"Version 1 to Version 2 Migration",id:"migration",level:2},{value:"Resource Use with Classic Queues",id:"resource-use",level:2},{value:"File Handle Usage with Classic Queues",id:"file-handles",level:3},{value:"Memory Footprint with Classic Queues",id:"memory",level:3},{value:"Alternate Message Store Index Implementations",id:"msg-store-index-implementations",level:2}];function h(e){let s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.header,{children:(0,t.jsx)(s.h1,{id:"classic-queues",children:"Classic Queues"})}),"\n",(0,t.jsx)(s.h2,{id:"overview",children:"What is a Classic Queue"}),"\n",(0,t.jsxs)(s.p,{children:["A RabbitMQ classic queue (the original queue type) is a versatile queue type suitable for use cases where data safety is not a priority because the data stored in classic queues is not replicated.\nClassic queues uses the ",(0,t.jsx)(s.strong,{children:"non-replicated"})," FIFO queue implementation."]}),"\n",(0,t.jsxs)(s.p,{children:["If data safety is a priority, the recommendation is to use ",(0,t.jsx)(s.a,{href:"./quorum-queues",children:"quorum queues"})," and ",(0,t.jsx)(s.a,{href:"./streams",children:"streams"})," instead of classic queues."]}),"\n",(0,t.jsx)(s.p,{children:"Classic queues are the default queue type\nas long as the default queue type is not overridden for the virtual host."}),"\n",(0,t.jsx)(s.h2,{id:"features",children:"Classic Queue Features"}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues fully support ",(0,t.jsx)(s.a,{href:"./queues",children:"queue exclusivity"}),",\n",(0,t.jsx)(s.a,{href:"./ttl",children:"queue and message TTL (Time-To-Live)"}),",\n",(0,t.jsx)(s.a,{href:"./maxlength",children:"queue length limits"}),",\n",(0,t.jsx)(s.a,{href:"./priority",children:"message priority"}),",\n",(0,t.jsx)(s.a,{href:"./consumer-priority",children:"consumer priority"}),"\nand adhere to settings ",(0,t.jsx)(s.a,{href:"./policies",children:"controlled using policies"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues support ",(0,t.jsx)(s.a,{href:"./dlx",children:"dead letter exchanges"})," with\nthe exception of ",(0,t.jsx)(s.a,{href:"./quorum-queues#dead-lettering",children:"at-least-once dead-lettering"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues do not support ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Poison_message",children:"poison message handling"}),",\nunlike ",(0,t.jsx)(s.a,{href:"./quorum-queues",children:"quorum queues"}),". Classic queues also do not\nsupport at-least-once dead-lettering, supported by quorum queues."]}),"\n",(0,t.jsxs)(s.p,{children:[(0,t.jsx)(s.a,{href:"./consumer-prefetch",children:"Per-consumer QoS prefetch"})," should be\npreferred over global QoS prefetch, even though classic queues support\nboth options. Global QoS prefetch is a deprecated feature that will be\nremoved in ",(0,t.jsx)(s.strong,{children:"RabbitMQ 4.0"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["While classic queues can be declared as transient, this makes queue\nremoval difficult to reason about in case of node restarts during upgrades and such,\nso the use of transient queues is discouraged. Support for transient queues\nis deprecated and will be removed in ",(0,t.jsx)(s.strong,{children:"RabbitMQ 4.0"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues is a non-replicated queue type starting with RabbitMQ 4.0.\n",(0,t.jsx)(s.a,{href:"./quorum-queues",children:"Quorum queues"}
1)," and ",(0,t.jsx)(s.a,{href:"./streams",children:"streams"})," provide a better alternative when high availability and\ndata safety is required."]}),"\n",(0,t.jsx)(s.h2,{id:"persistence",children:"Persistence (Durable Storage) in Classic Queues"}),"\n",(0,t.jsx)(s.p,{children:"Classic queues use an on-disk index for storing message locations on disk\nas well as a message store for persisting messages."}),"\n",(0,t.jsxs)(s.p,{children:["Both ",(0,t.jsx)(s.a,{href:"./publishers#message-properties",children:"persistent and transient messages"}),"\nare always persisted to disk except when:"]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:"the queue is declared as transient or messages are transient"}),"\n",(0,t.jsx)(s.li,{children:"messages are smaller than the embedding threshold (defaults to 4096 bytes)"}),"\n",(0,t.jsx)(s.li,{children:"the queue is short (queues may keep up to 2048 messages in memory at most,\ndepending on the consumer delivery rate)"}),"\n"]}),"\n",(0,t.jsx)(s.p,{children:"In general messages are not kept in memory unless the rate of\nconsumption of messages is high enough that the messages that\nare in memory are expected to be consumed within the next\nsecond. Classic queues keep up to 2048 messages in memory,\ndepending on the consumer delivery rate. Larger messages are not read\ninto memory until the moment when they have to be sent to consumers."}),"\n",(0,t.jsxs)(s.p,{children:["Persisted messages may be ",(0,t.jsx)(s.strong,{children:"embedded"})," in the queue or sent\nto a ",(0,t.jsx)(s.strong,{children:"shared message store"}),". The decision to store messages\nin the queue or in the shared message store is based on the\nsize of the message, including headers. The shared message\nstore is more efficient at handling larger messages,\nparticularly when those messages are sent to multiple\nqueues."]}),"\n",(0,t.jsx)(s.p,{children:"The message location is written in the queue's index.\nEach queue has one index. The queue is responsible for\ntracking messages location as well as their position\nin the queue, and it persists this information in the\nindex."}),"\n",(0,t.jsxs)(s.p,{children:["Embedded messages are written in its queue index when\nusing classic queues version 1; and in its\n",(0,t.jsx)(s.strong,{children:"per-queue message store"})," when using classic\nqueues version 2."]}),"\n",(0,t.jsx)(s.p,{children:"Larger messages are written to a shared message store.\nEach vhost has two such stores: one for persistent\nmessages and one for transient messages, but they\nare usually considered together as the shared message\nstore. All queues in the vhost use the same message\nstore."}),"\n",(0,t.jsx)(s.h2,{id:"versions",children:"Classic Queue Storage Implementation Versions"}),"\n",(0,t.jsx)(s.p,{children:"There are currently two classic queue versions (implementation).\nDepending on the version, classic queues will\nuse a different index for messages, as well\nas operate differently regarding the embedding of small messages in\nthe index."}),"\n",(0,t.jsx)(s.h4,{id:"classic-queue-implementation-version-1",children:"Classic Queue Implementation Version 1"}),"\n",(0,t.jsx)(s.p,{children:"RabbitMQ 4.0 removed support for classic queues version 1."}),"\n",(0,t.jsx)(s.h3,{id:"classic-queue-implementation-version-2",children:"Classic Queue Implementation Version 2"}),"\n",(0,t.jsx)(s.p,{children:"The index in version 2 only uses segment files and only loads messages from\ndisk when necessary. It will load more messages based on the\ncurrent consumption rate. Version 2 does not embed messages\nin its index, instead a per-queue message store is used."}),"\n",(0,t.jsxs)(s.p,{children:["Version 2 was added in ",(0,t.jsx)(s.strong,{children:"RabbitMQ 3.10.0"})," and was significantly\nimproved in ",(0,t.jsx)(s.strong,{children:"RabbitMQ 3.12.0"}),". Version 1 queues are no longer\nsupported starting with ",(0,t.jsx)(s.strong,{children:"RabbitMQ 4.0"}),"."]}),"\n",(0,t.jsx)(s.h2,{id:"migration",children:"Version 1 to Version 2 Migration"}),"\n",(0,t.jsx)(s.p,{children:"When a RabbitMQ 4.0 node starts, it will automatically migrate any existing\nv1 queues to v2 (it will rewrite their on-disk representation)."}),"\n",(0,t.jsx)(s.p,{children:"Note that for large queues the conversion\nmay take some time and results in the queue being unavailable while\nthe conversion is running. As a point of reference, on our test machine,\nthe migration takes:"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:"2 seconds to migrate 1000 queues with 1000 100-byte messages each"}),"\n",(0,t.jsx)(s.li,{children:"9 seconds to migrate a queue with 1 million 100-byte messages"}),"\n",(0,t.jsx)(s.li,{children:"3 seconds to migrate a queue with 1 million 5000-byte messages\n(with the default embedding size of 4096 bytes, 5000-byte\nmessages are in the message store so there is less data to migrate)"}),"\n"]}),"\n",(0,t.jsx)(s.p,{children:"Given the numbers above, unless there is a lot of queues with a lot of messages,\nthe migration should complete in a matter of seconds."}),"\n",(0,t.jsx)(s.p,{children:"It is possible to perform this migration before upgrading to RabbitMQ 4.0.\nPlease refer to the RabbitMQ 3.13 documentation for details."}),"\n",(0,t.jsx)(s.h2,{id:"resource-use",children:"Resource Use with Classic Queues"}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues aim to provide reasonably good throughput in the majority\nof situations without configuration. However, some configuration is\nsometimes useful. This section covers a few configurable values that\naffect stability, throughput, latency and I/O characteristics of a node.\nConsider getting accustomed to ",(0,t.jsx)(s.a,{href:"https://rabbitmq.github.io/rabbitmq-perf-test/stable/htmlsingle/",children:"benchmarking with PerfTest"}),"\nin addition to get the most out of your queues."]}),"\n",(0,t.jsx)(s.p,{children:"Some related information includes:"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"./configure",children:"Main configuration guide"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"./relocate",children:"File and Directory Locations"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"./runtime",children:"Runtime Tuning"})}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"./queues#runtime-characteristics",children:"Queues"})," and their runtime characteristics"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"file-handles",children:"File Handle Usage with Classic Queues"}),"\n",(0,t.jsxs)(s.p,{children:["The RabbitMQ server is limited in the ",(0,t.jsx)(s.a,{href:"./networking#open-file-handle-limit",children:"number of file handles"}
1),"\nit can open. Every running network connection requires one file handle,\nand the rest are available for queues to use."]}),"\n",(0,t.jsx)(s.p,{children:"Classic queues version 2 do not try to accommodate for low numbers\nof file descriptors anymore like v1 used to do. They expect servers to\nhave a large file descriptor limit configured and to always be able to open a\nnew file handle when necessary. The index keeps up to 4 file\nhandles open at any time, and the per-queue store keeps 1\nfile handle open but may open another one when flushing data\nto disk. This means that each queue needs up to 6 file\ndescriptors available to properly function, in theory. In\npractice only busy queues will need that many; other queues\nwill function just fine with 3 or 4 file handles."}),"\n",(0,t.jsx)(s.p,{children:"As a result of not using the file handle management subsystem,\nversion 2 does not track as many I/O statistics; only the numbers\nof reads and writes. Other metrics can be obtained at the OS level."}),"\n",(0,t.jsx)(s.h3,{id:"memory",children:"Memory Footprint with Classic Queues"}),"\n",(0,t.jsxs)(s.p,{children:["Classic queues may keep up to 2048 messages in memory, depending\non the consume rate. Classic queues will, however, avoid reading\nlarger messages from disk too early. In ",(0,t.jsx)(s.strong,{children:"RabbitMQ 3.12"})," this\nmeans messages larger than the embedded threshold (by default, 4096 bytes)."]}),"\n",(0,t.jsxs)(s.p,{children:["The index and per-queue store in version 2 buffer entries.\nThis is typically not a concern as far as the index is concerned\nsince it only tracks metadata. The per-queue store will however\nuse up to 1MB of memory by default (512KB in the write buffer\nand 512KB in a cache). When flushing to disk the store will\nfirst clear the cache then move the messages in the write buffer\nto the cache, effectively replacing the data in the cache with\nthe data in the write buffer. The size of the write buffer and\nthe cache are therefore linked. It can be configured using the\nadvanced config via rabbit's ",(0,t.jsx)(s.code,{children:"classic_queue_store_v2_max_cache_size"}),"\nparameter."]}),"\n",(0,t.jsx)(s.p,{children:"Idle queues will reduce their memory usage. This can sometimes\nresult in surprising spikes when performing operations that\naffect many queues, such as defining new policies. In that case\nthe queues will need to allocate more memory again. The more\nqueues, the bigger the spike should be expected."}),"\n",(0,t.jsx)(s.p,{children:"The shared message store needs an index. The default message store\nindex uses a small amount of memory for every message in the store."}),"\n",(0,t.jsx)(s.h2,{id:"msg-store-index-implementations",children:"Alternate Message Store Index Implementations"}),"\n",(0,t.jsx)(s.p,{children:"As mentioned above, each message which is written to the message\nstore uses a small amount of memory for its index entry. The\nmessage store index is pluggable in RabbitMQ, and other\nimplementations are available as plugins which can remove this\nlimitation."}),"\n",(0,t.jsx)(s.p,{children:"The reason they are not shipped with the RabbitMQ distribution is\nthat they all use native code. Note that such plugins typically\nmake the message store run more slowly."})]})}function d(e={}){let{wrapper:s}={...(0,a.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},28453(e,s,n){n.d(s,{R:()=>r,x:()=>o});var i=n(96540);let t={},a=i.createContext(t);function r(e){let s=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function o(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(a.Provider,{value:s},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.