A common community question is whether JetStream scheduled messages can be used in a stream configured with Interest retention.
Yes, scheduled messages can be used with an Interest-retention stream, but Interest retention still applies.
That means:
Limits-retention stream with a TTL on the delayed message, or a stream-level MaxAge, is a better fit.With Interest retention, JetStream retains messages only while there is matching consumer interest. If there is no matching interest, the stream is allowed to remove the message.
Scheduled messages do not bypass that rule. Until a scheduled message becomes due, the schedule is held in the stream as a stored message. If the stream uses Interest retention and no consumer has matching interest in that message’s subject, the stored schedule can be removed right away — before it ever fires.
This behavior is intentional: Interest retention means “keep messages for interested consumers,” not “keep messages until some later business event.”
No. A scheduled message is tied to the stream where the schedule is created. You should not design around creating a schedule in stream A and expecting the delayed message to be published into stream B.
If you want scheduled messages to be retained independently from your main processing stream, model that directly with the stream that owns the scheduled workload rather than trying to schedule across streams.
You can make scheduled messages survive Interest retention by ensuring there is a matching consumer interest. However, creating a consumer solely to hold interest is generally not recommended.
A paused or idle consumer is not free:
Pausing a consumer may reduce active delivery work compared with a consumer that is continuously receiving messages, but it does not make the design costless. Without workload-specific testing, it is better not to rely on a paused consumer as the retention mechanism for scheduled messages.
If you only expect a very small number of scheduled messages, the cost may be acceptable in practice. Still, it is worth treating this as a tradeoff rather than the intended default pattern.
For scheduled work, a Limits-retention stream is often the cleaner design.
Instead of retaining messages based on consumer interest, configure the stream so that scheduled messages are bounded by explicit limits. Depending on your requirements, that might include:
MaxAge so old scheduled or unprocessed messages are eventually removed;Keep one tradeoff in mind: Limits retention does not remove a message just because a consumer has acknowledged it. Messages persist until a configured bound — MaxAge, MaxMsgs, MaxBytes, or a per-message TTL — is reached. If you specifically need messages to be deleted as soon as they are processed, that delete-on-acknowledgment behavior is what Interest retention provides. Weigh that before switching a stream to Limits.
This design separates two concerns:
That tends to be easier to reason about than using a synthetic consumer to prevent Interest retention from deleting schedules.
Interest retention can still be a good fit when consumers already represent the true lifecycle of the data.
For example, it may be reasonable if:
It is less suitable when the only reason for a consumer to exist is to keep scheduled messages from being deleted.
Use this checklist when choosing a design:
Limits retention.MaxAge.Scheduled messages can work with Interest retention, but the retention policy remains active while the message is scheduled. If there is no matching interest, the schedule can be removed before it is due.
For most scheduling workflows, prefer a Limits-retention stream with explicit expiration controls such as TTL or MaxAge. Use Interest retention when consumer interest truly represents the desired message lifecycle, not as a workaround that depends on an idle or paused consumer.
Want help from the NATS experts? Meet with our architects to get help tailored to your use case and environment.



News and content from across the community