RabbitMQ
debt(d8/e5/b7/t7)
Closest to 'silent in production until users hit it' (d9, scored d8). Per detection_hints.automated=no and code_pattern, missing durability/DLX/ack issues only surface on broker restart or under load; rabbitmq-management UI can reveal missing DLX or non-durable queues on inspection, slightly better than fully silent.
Closest to 'touches multiple files / significant refactor in one component' (e5). quick_fix requires coordinating exchange type, queue durable=true, AND message persistence across producers and consumers — not a one-line swap, but contained within the messaging layer.
Closest to 'strong gravitational pull' (b7). applies_to spans web/cli/queue-worker contexts; RabbitMQ as a broker shapes service boundaries, deployment topology, and failure-handling patterns across the system per why_it_matters (decoupling producers/consumers).
Closest to 'serious trap' (t7). The misconception is explicit: developers reasonably assume durable queue = durable messages, but both flags are required independently. This contradicts the intuitive 'durable container holds durable contents' mental model.
Also Known As
TL;DR
Explanation
RabbitMQ's model: Producer → Exchange → Queue → Consumer. Exchanges route messages: direct (exact routing key), fanout (all bound queues), topic (wildcard routing keys), headers. Message durability: declare the queue as durable and messages as persistent to survive broker restarts. Acknowledgements: the consumer calls basic_ack after processing; unacked messages redeliver on consumer disconnect. Prefetch count controls how many unacked messages a consumer holds — prevents slow consumers from starving others.
Diagram
flowchart LR
PUB[Publisher] --> EX{Exchange}
subgraph Routing Types
EX -->|direct: routing key match| Q1[Queue: orders]
EX -->|fanout: all queues| Q2[Queue: logs]
EX -->|fanout: all queues| Q3[Queue: analytics]
EX -->|topic: pattern match| Q4[Queue: payments.uk.*]
end
Q1 --> C1[Consumer 1]
Q2 --> C2[Consumer 2]
Q3 --> C3[Consumer 3]
Q4 --> C4[Consumer 4]
style EX fill:#6e40c9,color:#fff
style Q1 fill:#238636,color:#fff
style Q2 fill:#1f6feb,color:#fff
style Q3 fill:#1f6feb,color:#fff
style Q4 fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Not setting prefetch_count — one slow consumer takes all messages from the queue, starving other consumers.
- Declaring queue as durable but not marking messages as persistent — messages lost on broker restart.
- Not handling connection failures — AMQP connections drop; implement reconnection logic.
- No dead letter exchange — failed messages disappear silently without a DLX configured.
Code Examples
// Messages lost on restart — durable queue, non-persistent messages:
$channel->queue_declare('orders', false, true, false, false); // durable=true
$channel->basic_publish(
new AMQPMessage('order data'), // No delivery_mode=2 — not persistent!
'', 'orders'
);
// Broker restart: queue survives, messages gone
// Fully durable setup:
$channel->queue_declare('orders', false, true, false, false); // durable
$channel->basic_publish(
new AMQPMessage('order data', [
'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT, // Persistent
]),
'', 'orders'
);
$channel->basic_qos(null, 1, null); // Prefetch: 1 unacked message per consumer
$channel->basic_consume('orders', '', false, false, false, false, $callback);
// Worker acks after successful processing: $msg->ack()