diff --git a/src/components/classic/documentation/how-do-i-set-the-message-expiration.md b/src/components/classic/documentation/how-do-i-set-the-message-expiration.md
index b99686e1e..fe8b651c8 100644
--- a/src/components/classic/documentation/how-do-i-set-the-message-expiration.md
+++ b/src/components/classic/documentation/how-do-i-set-the-message-expiration.md
@@ -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).
+
diff --git a/src/components/classic/documentation/message-expiry.md b/src/components/classic/documentation/message-expiry.md
new file mode 100644
index 000000000..2f46a03d9
--- /dev/null
+++ b/src/components/classic/documentation/message-expiry.md
@@ -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)
+
diff --git a/src/components/classic/documentation/message-features.md b/src/components/classic/documentation/message-features.md
index d7155bd51..e78193c47 100644
--- a/src/components/classic/documentation/message-features.md
+++ b/src/components/classic/documentation/message-features.md
@@ -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)
diff --git a/src/components/classic/documentation/sitemap.md b/src/components/classic/documentation/sitemap.md
index 4e6416971..474af7201 100644
--- a/src/components/classic/documentation/sitemap.md
+++ b/src/components/classic/documentation/sitemap.md
@@ -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)
diff --git a/src/components/classic/documentation/slow-consumer-handling.md b/src/components/classic/documentation/slow-consumer-handling.md
index 36218a56a..badeb1733 100644
--- a/src/components/classic/documentation/slow-consumer-handling.md
+++ b/src/components/classic/documentation/slow-consumer-handling.md
@@ -54,6 +54,16 @@ We have a `MessageEvictionStrategy` which is used to decide which message shoul
```
+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"`:
+
+```
+
+```
+
+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:
@@ -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
-