Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ JMSExpiration on a message is set by the MessageProducer in JMS - either via
* [producer.setTimeToLive()](http://java.sun.com/j2ee/1.4/docs/api/javax/jms/MessageProducer.html#setTimeToLive(long))
* [producer.send(Destination, Message, int, int, long)](http://java.sun.com/j2ee/1.4/docs/api/javax/jms/MessageProducer.html#send(javax.jms.Destination,%20javax.jms.Message,%20int,%20int,%20long))

For the end-to-end view of how TTL becomes `JMSExpiration`, how the broker enforces expiry, and why clock synchronization matters, see [Message Expiry](message-expiry).

44 changes: 44 additions & 0 deletions src/components/classic/documentation/message-expiry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
layout: default_md
title: Message Expiry
title-class: page-title-classic
type: classic
---

[Features](features) > [Message Features](message-features) > [Message Expiry](message-expiry)


Apache ActiveMQ Classic handles message expiry in two parts:

1. **The client sets the expiration time when it sends the message.**
2. **The broker checks that expiration time and discards expired messages.**

When a JMS producer sets a time-to-live (TTL), ActiveMQ Classic converts that TTL into an absolute `JMSExpiration` value when the message is sent. A TTL of `0` means the message never expires.

At the broker, expired messages can be removed in several places, including when a message arrives, while messages are being held for dispatch, and during periodic destination scans. Consumers may also filter expired messages before delivery.

## Client-side expiry

In JMS, message expiration is controlled by the producer:

* [`MessageProducer.setTimeToLive(long)`](how-do-i-set-the-message-expiration)
* [`MessageProducer.send(...)`](how-do-i-set-the-message-expiration)

ActiveMQ Classic stores the TTL as an absolute expiration timestamp on the message. That timestamp is based on the sending machine's clock.

## Broker-side expiry

The broker checks the stored expiration timestamp against its own clock and removes expired messages as they are encountered. Because of that, expiry is not purely a client-side concept: the broker still has to enforce it.

For that reason, the clocks on all machines involved — producers, brokers, and consumers — should be kept in sync. If the machines are not time-synchronized, a message may appear to expire early or late depending on which clock is ahead.

## Consumer expiry checks

The ActiveMQ Classic client also performs expiry checks before delivering messages to application code. This helps prevent expired messages from being consumed accidentally.

## Related documentation

* [How do I set the message expiration](how-do-i-set-the-message-expiration)
* [Message Redelivery and DLQ Handling](message-redelivery-and-dlq-handling)
* [Slow Consumer Handling](slow-consumer-handling)

1 change: 1 addition & 0 deletions src/components/classic/documentation/message-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type: classic
* [Advisory Message](advisory-message)
* [Blob Messages](blob-messages)
* [Delay and Schedule Message Delivery](delay-and-schedule-message-delivery)
* [Message Expiry](message-expiry)
* [JMS Streams](jms-streams)
* [Message Transformation](message-transformation)
* [ObjectMessage](objectmessage)
Expand Down
1 change: 1 addition & 0 deletions src/components/classic/documentation/sitemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ Features
* [Advisory Message](advisory-message)
* [Blob Messages](blob-messages)
* [Delay and Schedule Message Delivery](delay-and-schedule-message-delivery)
* [Message Expiry](message-expiry)
* [JMS Streams](jms-streams)
* [Message Transformation](message-transformation)
* [ObjectMessage](objectmessage)
Expand Down
11 changes: 10 additions & 1 deletion src/components/classic/documentation/slow-consumer-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ We have a `MessageEvictionStrategy` which is used to decide which message shoul
<oldestMessageEvictionStrategy/>
```

By default, ActiveMQ will frist remove any expired messages from the slow-consumer pending buffer before evicting non-expired messages.

If your messages do not use TTL or you do not want this behavior you can disable it with `expiryScanEnabled="false"`:

```
<oldestMessageEvictionStrategy expiryScanEnabled="false"/>
```

Messages will still be subject to expiry checks on the client. For the full client/broker expiry flow and the clock synchronization caveat, see [Message Expiry](message-expiry). The default is `expiryScanEnabled="true"`.

However, you can write your own to use some application specific way of choosing messages for eviction. For example, if you are sending market data price updates you may wish to find an older price value, which might not be the oldest message.

Example:
Expand Down Expand Up @@ -140,4 +150,3 @@ Statistic|Definition
---|---
`discarded`|The count of how many messages have been discarded during the lifetime of the subscription due to it being a slow consumer
`matched`|The current number of messages matched and to be dispatched to the subscription as soon as some capacity is available in the prefetch buffer. So a non-zero value implies that the prefetch buffer is full for this subscription