Skip to content

Set RabbitMQ memory and disk limits

Severity: lowApplies to: RabbitMQ 3.x / 4.x
The fix/etc/rabbitmq/rabbitmq.conf
vm_memory_high_watermark.relative = 0.6
disk_free_limit.absolute = 2GB
# Bound queues so one runaway can't consume everything:
Terminal window
rabbitmqctl set_policy max-len ".*" '{"max-length":100000,"overflow":"reject-publish"}' --apply-to queues

A queue with no consumer, or a consumer slower than its publishers, grows without bound. RabbitMQ holds messages in memory (and pages to disk), so an unbounded queue eventually exhausts one or the other — and when it does, RabbitMQ blocks all publishers across the whole broker to protect itself.

That’s the failure mode worth understanding: it’s not one queue that stops, it’s every publisher on the broker that gets flow-controlled to a halt, because the node hit its memory or disk limit. One misbehaving application takes down messaging for all of them.

This closes no security exposure, which is why it’s low. What it prevents is a single overload — accidental or deliberate — becoming a broker-wide outage.

RabbitMQ has built-in alarms that block publishing before the host actually runs out:

  • vm_memory_high_watermark — when the node’s memory use crosses this fraction of system RAM (0.6 = 60%), publishers are blocked until it drops. Default is 0.6; the risk is a host where RabbitMQ shares RAM with other services and 60% of total is more than RabbitMQ should use. Set it to what RabbitMQ should actually be allowed.
  • disk_free_limit — when free disk falls below this, publishing blocks. The default is tied to RAM size and is often too low; a broker that pages a large backlog to disk can fill the volume, and a full disk is a hard stop. 2GB absolute is a safer floor on most hosts.

These are safety valves, not tuning knobs. They turn “the host ran out of memory and the node crashed” into “publishing paused, consumers caught up, publishing resumed.”

The watermarks protect the node; queue length limits protect against the queue that shouldn’t have grown in the first place:

Terminal window
rabbitmqctl set_policy max-len "^orders\." \
'{"max-length":100000,"overflow":"reject-publish"}' --apply-to queues

overflow decides what happens at the limit:

  • reject-publish — refuse new messages, so the publisher learns immediately that something is wrong. Usually what you want: fail loud.
  • drop-head — silently discard the oldest messages to make room. Right for telemetry where the newest data matters and old data is worthless; wrong for anything where losing a message is a problem.

A message TTL is the other bound — messages older than a limit expire — which suits queues where stale work is pointless.

Modern RabbitMQ (3.12+) makes queues store messages on disk by default rather than holding them in memory, which changes the memory picture substantially — a large backlog is far less likely to hit the memory watermark than it was on older versions. Quorum queues (the recommended replicated queue type in 4.x) are disk-based and more predictable under load. If you’re designing new, quorum queues plus a max-length are a more robust combination than classic queues with tuned watermarks.