RabbitMQ Message TTL

TTL stands for Time-To-Live. In RabbitMQ, message TTL sets an expiry on messages — after a set amount of time, an unread message automatically expires. This prevents queues from filling up with stale messages that are no longer useful to consume.

The Newspaper Stand Analogy

A newspaper stand sells today's papers. If a copy is not sold by the end of the day, the stand owner throws it away — yesterday's news is not worth reading. Message TTL works the same way. If a message is not consumed within its expiry time, RabbitMQ discards it (or sends it to a dead letter queue).

Two Ways to Set TTL

1. Queue-Level TTL (applies to all messages in the queue)

Set the x-message-ttl argument when declaring a queue. Every message in that queue expires after the specified time in milliseconds, regardless of the individual message's own settings.

channel.queue_declare(
    queue='short-lived-tasks',
    durable=True,
    arguments={
        'x-message-ttl': 60000  # all messages expire after 60 seconds
    }
)

2. Per-Message TTL (applies to one specific message)

Set the expiration property on a message when publishing. Only that specific message has the expiry, not the entire queue.

channel.basic_publish(
    exchange='',
    routing_key='my-queue',
    body='This message expires soon',
    properties=pika.BasicProperties(
        expiration='30000'  # expires after 30 seconds (as a string)
    )
)

When Both TTL Values Are Set

If a queue has x-message-ttl set AND an individual message has its own expiration property, the message expires at whichever time comes first.

Queue TTL:   60,000 ms (60 seconds)
Message TTL: 10,000 ms (10 seconds)
--> Message expires after 10 seconds (the shorter time wins)

What Happens When a Message Expires

An expired message is either:

  • Discarded silently — dropped from the queue and gone forever
  • Dead-lettered — routed to a dead letter exchange (DLX) if the queue has x-dead-letter-exchange configured

Dead-lettering expired messages is the better production approach because it lets you audit, retry, or log the expired messages.

[Queue: "flash-sale-queue"]
  x-message-ttl: 300000 (5 minutes)
  x-dead-letter-exchange: "expired-dlx"
       |
       | message TTL runs out
       v
[expired-dlx]
       |
       v
[expired-flash-sale-queue]
  (for review or refund processing)

Queue Expiry vs Message Expiry

RabbitMQ also supports queue-level expiry via x-expires. This is different from message TTL. x-expires deletes the entire queue (including all its messages) if the queue has had no consumers for the specified time. It is useful for cleaning up abandoned temporary queues.

channel.queue_declare(
    queue='temp-session-queue',
    arguments={
        'x-expires': 1800000  # delete the queue itself after 30 min of no consumers
    }
)

Do not confuse x-message-ttl (expires individual messages) with x-expires (expires the whole queue).

TTL Precision

RabbitMQ checks for expired messages when they reach the head of the queue (the front, next in line for delivery). This means a message buried deep in a long queue may survive slightly longer than its TTL suggests — it is not evicted until it reaches the front. For queue-level TTL, expired messages are removed efficiently as soon as they are next to be delivered. Per-message TTL with varying expiration values can cause out-of-order expiry.

Real-World Use Cases for Message TTL

Session Tokens

A login service publishes a session token to a queue. The token is only valid for 15 minutes. Set x-message-ttl: 900000. If the consumer service is down for more than 15 minutes, expired tokens are automatically removed rather than processed by a consumer trying to validate a stale token.

Flash Sale Events

An e-commerce platform queues discount vouchers for a 1-hour flash sale. After the sale ends, any unread voucher messages expire automatically. Consumers never process vouchers from last week's sale.

Live Data Feeds

A stock price service publishes price updates every second. If a consumer is slow and falls behind, old price messages are useless. Set a short TTL (e.g., 5 seconds) so consumers always process fresh data rather than working through a backlog of stale prices.

OTP and Verification Codes

A two-factor authentication service queues OTP (One-Time Password) messages. OTPs expire after 5 minutes. Set expiration='300000' on each message. If the consumer has not processed the OTP in 5 minutes, it expires safely.

Checking TTL Configuration in the Management UI

Open the Queues tab and click on a queue. In the Features column, a queue with x-message-ttl shows the TTL value. You can also see TTL in the queue's arguments section at the bottom of the detail page.

TTL and Message Persistence

Setting a message as persistent (delivery_mode=2) does not override TTL. A persistent message still expires if its TTL runs out, even if it was saved to disk. Persistence protects against broker restart; TTL protects against message staleness. They are independent settings.

Summary

Message TTL in RabbitMQ controls how long an unread message can wait in a queue before expiring. Set queue-level TTL using x-message-ttl to apply a uniform expiry to all messages. Set per-message TTL using the expiration property for individual control. The shorter TTL always wins when both are set. Expired messages are either silently dropped or sent to a dead letter exchange. TTL is essential for keeping queues clean and ensuring consumers never process outdated data.

Leave a Comment

Your email address will not be published. Required fields are marked *