Skip to content

Flow Control & Alarms

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"]
An alarm turns backpressure back onto publishers

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.

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.

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.

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-length or 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.
What does RabbitMQ do to publishers when a memory or disk alarm fires?
A connection shows the state "flow" in the management UI. What does that mean?
What problem do lazy queues (and classic v2 / quorum storage) address?
What is the best way to keep alarms and flow control rare?