Home/Learn/RabbitMQ/Lazy Queues

Lazy Queues

Intermediate
Advanced Queue Types

Lazy queues write messages to disk immediately, reducing memory usage for deep queues; ideal when consumers are slow and a large backlog must be held without crashing the broker.

Overview

By default, RabbitMQ keeps as many messages as possible in memory (RAM) for fast delivery. When a large backlog builds up, the broker can exhaust RAM and trigger a memory alarm, blocking all producers. Lazy Queues (declared with x-queue-mode=lazy or the modern default-queue-type=classic + lazy policy) write all messages to disk immediately and load them into memory only on consumer demand. This dramatically reduces RAM usage at the cost of higher disk I/O and slightly higher latency. In RabbitMQ 3.12+, classic queues are lazy by default.

Declaring a Lazy Queue

Set x-queue-mode=lazy when declaring the queue, or apply a policy to convert existing queues. In RabbitMQ 3.12+ classic queues are lazy by default.

Java + Shell — declaring and enabling lazy queues
// Spring AMQP — declare a lazy queue
@Bean
public Queue lazyOrderQueue() {
    return QueueBuilder.durable("orders.processing")
        .lazy()    // x-queue-mode=lazy
        .build();
}

// Or manually via arguments
@Bean
public Queue lazyQueue() {
    return QueueBuilder.durable("bulk-exports")
        .withArgument("x-queue-mode", "lazy")
        .build();
}

# Apply lazy mode to existing queues via management API or CLI
# (no restart required — takes effect for new messages)
rabbitmqctl set_policy lazy-queues ".*" \
  '{"queue-mode":"lazy"}' \
  --apply-to queues

# RabbitMQ 3.12+ — classic queues are lazy by default
# Explicitly set to default (in-memory) mode:
@Bean
public Queue defaultModeQueue() {
    return QueueBuilder.durable("hot-path")
        .withArgument("x-queue-mode", "default")  // in-memory (legacy fast mode)
        .build();
}

Memory Watermark & Flow Control

When the broker hits its memory watermark (default 40% of RAM), it blocks all producer connections. Lazy queues prevent this by keeping messages on disk. Monitor memory usage and set an appropriate watermark.

rabbitmq.conf + Shell — memory watermark
# Memory watermark — broker blocks producers when RAM usage exceeds this
# Default: 40% of system RAM
# rabbitmq.conf:
vm_memory_high_watermark.relative = 0.4   # 40% of total RAM
# Or absolute:
vm_memory_high_watermark.absolute = 2GB

# Disk free alarm — blocks producers when disk space drops below this
disk_free_limit.absolute = 2GB

# Lazy queue benefit:
# Normal queue:  messages in RAM → broker may hit watermark and block producers
# Lazy queue:    messages on disk → RAM used only for actively consumed messages

# Monitor memory usage via CLI
rabbitmqctl status | grep memory
# memory: [{total,{rss,1234567890}},...]

# Monitor via HTTP API
curl -u admin:pass http://localhost:15672/api/nodes/rabbit@hostname \
  | jq '{mem_used, mem_limit, disk_free}'

Lazy Queues vs Quorum Queues

Lazy queues and quorum queues both use disk-backed storage but serve different purposes. Quorum queues offer HA via Raft replication. Lazy (classic) queues offer memory-efficient single-node or mirrored storage. For new high-throughput deployments, quorum queues are recommended.

Conceptual — lazy classic vs quorum queues
// Comparison:
//
// ┌────────────────┬─────────────────────┬──────────────────────┐
// │ Property       │ Lazy Classic Queue  │ Quorum Queue         │
// ├────────────────┼─────────────────────┼──────────────────────┤
// │ Replication    │ Optional (mirroring)│ Always (Raft, ≥3)   │
// │ Disk write     │ Immediate (all msgs)│ Immediate (Raft log) │
// │ Memory use     │ Very low            │ Low                  │
// │ Message order  │ FIFO                │ FIFO                 │
// │ Priority queue │ Supported           │ Not supported        │
// │ Max msg size   │ Unlimited           │ Limited (~500 MB)    │
// │ Recommended    │ Legacy/large backlog│ HA production use    │
// └────────────────┴─────────────────────┴──────────────────────┘

// Prefer quorum queues for new HA deployments:
@Bean
public Queue quorumQueue() {
    return QueueBuilder.durable("orders.processing")
        .quorum()
        .build();
}

// Use lazy (classic) when:
// - Large backlog expected (batch jobs, slow consumers)
// - Single-node broker (no HA needed)
// - Priority queues required

Key Points to Remember

  • 1Lazy queues write messages to disk immediately, keeping RAM free for other operations.
  • 2Default queues keep messages in RAM and page to disk only under memory pressure.
  • 3The memory watermark (default 40% RAM) triggers producer blocking — lazy queues help avoid it.
  • 4In RabbitMQ 3.12+, classic queues are lazy by default.
  • 5Apply laziness via x-queue-mode=lazy declaration argument or a policy (no restart needed).
  • 6For new HA deployments, prefer quorum queues; use lazy classic queues for large backlog scenarios.

Interview Questions

Sign in to ask Aria
1

What is a lazy queue and why would you use it?

MediumAmazon
2

What happens when RabbitMQ hits its memory watermark?

MediumPivotal
3

What is the difference between a lazy queue and a quorum queue?

HardNetflix
4

How do you convert an existing queue to lazy mode without deleting it?

MediumRevolut
5

What is the default memory watermark in RabbitMQ and how do you change it?

EasyInfosys

Ask Aria about Lazy Queues

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…