Flow Control & Alarms
The fundamental imbalance
Section titled “The fundamental imbalance”A queue only stays healthy if, over time, consumers keep up with producers. When publishers persistently outrun consumers, the backlog grows, memory fills, and something has to give. RabbitMQ has several mechanisms — from gentle to firm — to keep an overloaded broker from crashing.
Alarms block publishers (backpressure by design)
Section titled “Alarms block publishers (backpressure by design)”You met alarms last lesson; here is what they feel like. When the memory high-watermark or the disk free-space limit is crossed, RabbitMQ raises an alarm and blocks all publishing connections. Publishers are paused — their publish calls stop making progress — while consumers keep draining the queues.
flowchart TB fast["Publishers (too fast)"] --> q["Queues fill memory rises"] q --> alarm["Memory high-watermark crossed → ALARM"] alarm --> block["Publishing connections BLOCKED"] cons["Consumers keep draining"] --> q block --> recover["memory drops → alarm clears → publishers resume"]
This is intentional backpressure: rather than accept messages until it dies, the broker pushes the pressure back onto producers. A well-behaved producer notices the block (clients expose a “connection blocked” signal) and slows down. A poorly-behaved one just piles up blocked publishes. Either way, the broker survives.
Per-connection flow control
Section titled “Per-connection flow control”Even before a global alarm, RabbitMQ applies internal flow control per connection: if a publisher sends faster than the broker can route and persist, the broker throttles that specific connection so it can’t overwhelm the internal pipeline. In the management UI, such a connection shows the state flow — a normal, healthy signal that this publisher is being paced, not an error.
Lazy queues and large backlogs
Section titled “Lazy queues and large backlogs”By default, classic queues try to keep messages in memory for speed. A very deep queue (millions of messages) can therefore consume a lot of RAM and trip the memory alarm. Lazy queues (and the newer classic-queue v2 storage) instead keep messages on disk, trading a little latency for a much smaller memory footprint — the right choice when backlogs can grow large. Quorum queues are always disk-based and handle deep backlogs well.
Design so alarms stay rare
Section titled “Design so alarms stay rare”Alarms and flow control are safety nets, not a running mode. If they fire regularly, the design is wrong. To keep them rare:
- Scale consumers so the ack rate matches the publish rate over time.
- Bound your queues with a
max-lengthor TTL so a runaway producer can’t grow the queue without limit (drop or dead-letter the overflow instead). - Use lazy or quorum queues for workloads that can legitimately build deep backlogs.
- Handle “connection blocked” in producers — back off instead of hammering.
- Alert on queue depth trending up so you scale consumers before the memory alarm fires.