Queue Arguments#
Beyond durable, exclusive and auto_delete, RabbitMQ configures a queue through optional arguments: a dictionary of x-* keys sent with the declaration. They control message TTL, queue length, overflow behavior, dead-lettering, priorities and more. The full list lives in the RabbitMQ documentation.
RabbitQueue forwards them through the arguments parameter:
from faststream.rabbit import RabbitQueue
queue = RabbitQueue(
"orders",
arguments={
"x-message-ttl": 60_000,
"x-max-length": 10_000,
"x-overflow": "reject-publish",
},
)
x-queue-type is set for you from the queue_type parameter, so don't put it into arguments. The accepted keys depend on that type, and RabbitQueue is typed accordingly: your type checker flags a key the chosen queue type doesn't support, and your editor can complete the rest.
Common Arguments#
| Argument | Queue types | Meaning |
|---|---|---|
x-message-ttl | classic, quorum | Milliseconds a message may wait in the queue before it expires. |
x-expires | classic, quorum | Milliseconds of no use (no consumers, no declarations) after which the queue is deleted. |
x-max-length | classic, quorum | Maximum number of ready messages. |
x-max-length-bytes | all | Maximum total body size of ready messages. |
x-overflow | classic, quorum | What to do at the limit: drop-head (default) or reject-publish; classic queues also accept reject-publish-dlx. |
x-single-active-consumer | classic, quorum | Deliver to one consumer at a time, failing over to the next one. |
x-dead-letter-exchange | classic, quorum | Exchange receiving rejected and expired messages. See below. |
x-dead-letter-routing-key | classic, quorum | Routing key to dead-letter with. Keeps the original key when unset. |
x-max-priority | classic | Enables message priorities up to this value. |
x-delivery-limit | quorum | Redeliveries after which a message is dropped or dead-lettered. |
x-max-age | stream | Retention of a stream, for example "7D". |
Arguments that belong to the consumer rather than the queue (x-stream-offset, x-priority) go to the subscriber's consume_args instead, as the stream example shows.
Queue arguments are immutable
RabbitMQ refuses to redeclare an existing queue with different arguments and fails the declaration with PRECONDITION_FAILED. To change the arguments of a queue that already exists on the server, delete that queue first or pick a new name.
Dead Letter Queue#
When a consumer rejects a message, or a message sits in a queue longer than its TTL, RabbitMQ can forward it to a dead letter exchange instead of dropping it. A queue bound to that exchange collects those messages, so you can inspect, alert on, or replay them later.
The dead-lettering rules live on the source queue as the x-dead-letter-exchange and x-dead-letter-routing-key arguments. The dead letter exchange and the queue bound to it are ordinary objects that you declare like any other:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | |
A rejected order goes to orders-dlx with the routing key orders, lands in orders-dead and reaches handle_dead_letter as the very same message, plus an x-death header that says why it was dead-lettered (rejected, expired, maxlen or delivery_limit) and from which queue. Subscribers start in the order they are declared, each one declaring its queue and exchange and consuming right away, so declare the dead letter subscriber first: orders-dlx and orders-dead then exist before the first order can be rejected.
The same path is taken by any message that expires after x-message-ttl milliseconds, and by messages a handler fails on with an unhandled exception, since the default acknowledgement policy rejects those too.
Use a dead letter queue whenever a handler can fail for a reason a retry won't fix (a malformed payload, a business rule violation): requeuing such a message only makes the same handler fail again. For transient failures, use a quorum queue with x-delivery-limit and ack_policy=AckPolicy.NACK_ON_ERROR: a failed message is requeued and redelivered that many times first, and dead-lettered only after that. Under the default REJECT_ON_ERROR policy a failure rejects the message without requeue, so it is dead-lettered right away.
Tip
Without x-dead-letter-routing-key, a message is dead-lettered with the routing key it was originally published with. That is handy when one dead letter exchange serves several queues: bind one dead letter queue per source routing key, or use a fanout exchange to collect everything in one place.