NEW: Free hands-on NATS workshops. Live sessions on NATS fundamentals, leaf nodes, AI agents on NATS, & more.
All posts

A common community question is whether JetStream scheduled messages can be used in a stream configured with Interest retention.

Short answer

Yes, scheduled messages can be used with an Interest-retention stream, but Interest retention still applies.

That means:

  • If there is no consumer interest for the scheduled message while it is stored in the stream, JetStream may remove it immediately.
  • Creating an idle or paused consumer only to keep interest on scheduled messages is usually not the best design.
  • A schedule created for one stream cannot be used to publish the delayed message into a different stream.
  • For many scheduling use cases, a Limits-retention stream with a TTL on the delayed message, or a stream-level MaxAge, is a better fit.

Why scheduled messages may disappear with Interest retention

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.”

Can I schedule on one stream and deliver to another?

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.

Should I create a paused or idle consumer to hold interest?

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:

  • It still creates consumer state that the server must manage.
  • Messages may remain retained because that consumer is considered interested.
  • In replicated streams, that consumer state and related stream state have additional coordination and storage costs.
  • It can become an operational footgun: deleting or changing that consumer may unexpectedly allow scheduled messages to be removed.

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.

A safer pattern: use Limits retention for scheduled work

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:

  • a per-message TTL on the delayed message, when available for your scheduling path;
  • a stream-level MaxAge so old scheduled or unprocessed messages are eventually removed;
  • size, message-count, or byte limits appropriate for the workload; and
  • monitoring for backlog growth and expired work.

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:

  1. Scheduling durability: the scheduled message should remain until it is due or expires.
  2. Processing lifecycle: consumers should process the due message according to your application semantics.

That tends to be easier to reason about than using a synthetic consumer to prevent Interest retention from deleting schedules.

When Interest retention can still be reasonable

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:

  • real consumers already exist for the scheduled-message subjects;
  • messages should be removed when all relevant interested consumers have processed them;
  • the consumer lifecycle is stable and well understood; and
  • losing consumer interest should intentionally allow messages to be removed.

It is less suitable when the only reason for a consumer to exist is to keep scheduled messages from being deleted.

Decision checklist

Use this checklist when choosing a design:

  • Do scheduled messages need to survive even when no processing consumer is currently interested? If yes, prefer Limits retention.
  • Do you need delayed messages to expire automatically? Consider a message TTL or stream MaxAge.
  • Are you creating a consumer only to prevent deletion? Reconsider the retention policy.
  • Is the stream replicated? Be more cautious about extra idle consumers and retained state.
  • Do you need to schedule into a different stream? Redesign around the fact that scheduled messages stay within the same stream.

Practical recommendation

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.

Get the NATS Newsletter

News and content from across the community


Cancel