Skip to main content Link Menu Expand (external link) Document Search Copy Copied

NATS Configuration

Table of contents
  1. Quick Setup
    1. 1. Add the dependency
    2. 2. Configure application.properties
    3. 3. Start NATS with JetStream enabled
  2. Connection Properties
    1. Authentication examples
    2. Connection resilience
  3. Stream Properties
    1. Retention policy guide
    2. Three-replica production setup
  4. Consumer Properties
    1. Tuning for slow handlers
    2. Tuning for high-throughput queues
  5. Naming Properties
  6. Auto-Provisioning
    1. Streams (rqueue.nats.auto-create-streams)
    2. DLQ streams (rqueue.nats.auto-create-dlq-stream)
    3. Consumers (rqueue.nats.auto-create-consumers)
    4. KV buckets (rqueue.nats.auto-create-kv-buckets)
  7. Locked-Down JetStream Accounts
    1. Pre-creating streams
    2. Pre-creating KV buckets
  8. Inspecting Runtime State
  9. Limitations

Rqueue supports NATS JetStream as a drop-in replacement for Redis. All listener, producer, and middleware APIs work identically — the only changes required are the dependency and two properties.

The NATS backend does not support delayed enqueue, scheduled messages, or periodic/cron jobs. Calls to enqueueIn, enqueueAt, and enqueuePeriodic throw UnsupportedOperationException at runtime. Use the Redis backend for workloads that need scheduling.


Quick Setup

1. Add the dependency

Add rqueue-nats alongside rqueue-spring-boot-starter:

Gradle

implementation 'com.github.sonus21:rqueue-spring-boot-starter:4.0.0-RELEASE'
implementation 'com.github.sonus21:rqueue-nats:4.0.0-RELEASE'

Maven

<dependency>
    <groupId>com.github.sonus21</groupId>
    <artifactId>rqueue-spring-boot-starter</artifactId>
    <version>4.0.0-RELEASE</version>
</dependency>
<dependency>
    <groupId>com.github.sonus21</groupId>
    <artifactId>rqueue-nats</artifactId>
    <version>4.0.0-RELEASE</version>
</dependency>

2. Configure application.properties

rqueue.backend=nats
rqueue.nats.connection.url=nats://localhost:4222

No RedisConnectionFactory bean is needed. All Rqueue listener, producer, and middleware annotations work without any code changes.

3. Start NATS with JetStream enabled

# native binary
nats-server -js

# Docker
docker run -p 4222:4222 nats:latest -js

At startup, Rqueue’s NatsStreamValidator and NatsKvBucketValidator provision all required streams and KV buckets automatically.


Connection Properties

All connection properties are under the rqueue.nats.connection prefix.

Property Type Default Description
url String nats://localhost:4222 Single NATS server URL.
username String Username for username/password authentication.
password String Password for username/password authentication.
token String Token for token-based authentication.
credentials-path String Path to a .creds file for NKey/JWT authentication.
tls boolean false Enable TLS for the connection.
connection-name String Logical name visible in NATS server monitoring.
connect-timeout Duration (client default) Maximum time to wait for initial connection.
reconnect-wait Duration (client default) Time to wait between reconnect attempts.
max-reconnects int -1 (unlimited) Maximum reconnect attempts.
ping-interval Duration (client default) Interval between server pings.

Authentication examples

Token authentication

rqueue.nats.connection.token=s3cr3t

Username / password

rqueue.nats.connection.username=rqueue
rqueue.nats.connection.password=s3cr3t

NKey / JWT credentials file

rqueue.nats.connection.credentials-path=/etc/nats/rqueue.creds

Connection resilience

# Retry for up to 10 minutes (120 attempts × 5 s wait)
rqueue.nats.connection.max-reconnects=120
rqueue.nats.connection.reconnect-wait=5s

Set max-reconnects=-1 (the default) for unlimited retries in production — NATS reconnects silently to any cluster node without dropping in-flight messages.


Stream Properties

Each registered queue maps to one or more JetStream streams. The defaults below apply to every stream Rqueue creates. All properties are under rqueue.nats.stream.

Property Type Default Description
replicas int 1 Number of stream replicas. Must not exceed the number of JetStream-enabled servers in the cluster.
storage String FILE Storage backend: FILE (durable) or MEMORY (faster, lost on restart).
retention String LIMITS Retention policy: LIMITS, INTEREST, or WORK_QUEUE.
max-age Duration 14d Maximum age of messages before automatic removal.
max-bytes long -1 (unlimited) Maximum total stream size in bytes.
max-messages long -1 (unlimited) Maximum number of messages in the stream.
discard-policy String OLD What to discard when limits are hit: OLD (oldest messages) or NEW (reject new publishes).
duplicate-window Duration 2m Server-side dedup window for the Nats-Msg-Id header.

duplicate-window must be less than or equal to max-age. Set it to cover the maximum time a publisher might retry the same message ID (e.g. after a crash recovery).

Retention policy guide

Value When to use
LIMITS (default) General-purpose queues. Messages are kept until age/size limits are hit.
INTEREST Fan-out / pub-sub patterns. Messages are removed once every active consumer has acked.
WORK_QUEUE Lowest storage overhead. Message is removed as soon as any consumer acks it. Use for non-fan-out queues where exactly-once delivery per message is the goal.

Three-replica production setup

rqueue.nats.stream.replicas=3
rqueue.nats.stream.storage=FILE
rqueue.nats.stream.max-age=7d
rqueue.nats.stream.duplicate-window=5m

Consumer Properties

Consumer properties control the durable pull consumers Rqueue creates for each (queue, consumerName) pair. All properties are under rqueue.nats.consumer.

Property Type Default Description
ack-wait Duration 30s Time the server waits for an ack before redelivering. Must be longer than your slowest message handler.
max-deliver long 3 Delivery attempts before a message is forwarded to the DLQ.
max-ack-pending long 1000 Maximum unacked messages a consumer can hold before the server stops delivering.
fetch-wait Duration 2s How long pop() blocks waiting for messages before returning empty.

ack-wait is the most important consumer setting. If a message handler takes longer than ack-wait, the server redelivers the message to another consumer, causing duplicate processing. Set it to at least 2× your 99th-percentile handler latency.

Tuning for slow handlers

# Handlers can take up to 5 minutes
rqueue.nats.consumer.ack-wait=6m
# Give each message 5 attempts before DLQ
rqueue.nats.consumer.max-deliver=5

Tuning for high-throughput queues

# Allow more unacked messages in-flight
rqueue.nats.consumer.max-ack-pending=5000
# Reduce idle wait to pick up bursts faster
rqueue.nats.consumer.fetch-wait=500ms

Naming Properties

Naming properties control how stream and subject names are derived from queue names. All properties are under rqueue.nats.naming.

Property Type Default Description
stream-prefix String rqueue-js- Prefix for every JetStream stream name.
subject-prefix String rqueue.js. Prefix for every JetStream subject.
dlq-suffix String -dlq Suffix appended to stream and subject names for DLQ streams.

For a queue named orders with priority sub-queues high and low and a DLQ, the default naming produces:

Purpose Stream name Subject
Main queue rqueue-js-orders rqueue.js.orders
Priority: high rqueue-js-orders-high rqueue.js.orders.high
Priority: low rqueue-js-orders-low rqueue.js.orders.low
Dead-letter queue rqueue-js-orders-dlq rqueue.js.orders.dlq

Change the prefixes before the first deployment. Renaming them afterward requires manually migrating or recreating all streams.


Auto-Provisioning

Streams (rqueue.nats.auto-create-streams)

When true (default), NatsStreamValidator creates every required stream at startup, immediately after all @RqueueListener methods are registered and before message pollers start. This means the hot publish/pop path never pays a getStreamInfo round-trip to confirm stream existence.

Set to false for accounts where credentials lack add_stream permission. The validator will instead check that every required stream exists and abort boot with a clear IllegalStateException listing all missing streams — a deterministic startup failure rather than a stream not found error on first enqueue.

DLQ streams (rqueue.nats.auto-create-dlq-stream)

When true, a dead-letter stream is automatically created for every queue whose @RqueueListener declares a deadLetterQueue. Default is false — enable it when you want the DLQ stream provisioned alongside the main stream without pre-creating it manually.

Consumers (rqueue.nats.auto-create-consumers)

When true (default), durable pull consumers are created lazily on the first pop call for each (stream, consumerName) pair and the subscription is cached in-process. There is no per-pop round-trip after warm-up.

Set to false to fail-fast on missing consumers instead of creating them.

KV buckets (rqueue.nats.auto-create-kv-buckets)

Rqueue uses six shared KV buckets for state that Redis stores in keys, hashes, and sorted sets:

Bucket Purpose TTL
rqueue-queue-config Per-queue configuration and DLQ wiring None (persists)
rqueue-jobs Job execution history per message ID rqueue.message.durability (default 7 days)
rqueue-locks Distributed locks for scheduler leadership Set per lock acquisition
rqueue-message-metadata Per-message delivery status and retry count None
rqueue-workers Worker process info (host, PID, last-seen) rqueue.worker.registry.worker.ttl (default 300 s)
rqueue-worker-heartbeats Per-(queue, worker) heartbeats rqueue.worker.registry.queue.ttl (default 3600 s)

When auto-create-kv-buckets=true (default), each store lazily creates its bucket on first use. When set to false, NatsKvBucketValidator walks every bucket and aborts boot listing any that are missing.


Locked-Down JetStream Accounts

For deployments where application credentials cannot call add_stream or kv_create at runtime, disable all auto-provisioning and pre-create every resource before starting the application:

rqueue.nats.auto-create-streams=false
rqueue.nats.auto-create-consumers=false
rqueue.nats.auto-create-dlq-stream=false
rqueue.nats.auto-create-kv-buckets=false

Pre-creating streams

For a queue orders with priorities high / low and a DLQ:

nats stream add rqueue-js-orders \
    --subjects "rqueue.js.orders" \
    --storage file --replicas 3 --retention limits

nats stream add rqueue-js-orders-high \
    --subjects "rqueue.js.orders.high" \
    --storage file --replicas 3 --retention limits

nats stream add rqueue-js-orders-low \
    --subjects "rqueue.js.orders.low" \
    --storage file --replicas 3 --retention limits

nats stream add rqueue-js-orders-dlq \
    --subjects "rqueue.js.orders.dlq" \
    --storage file --replicas 3 --retention limits

Pre-creating KV buckets

Match TTL values to your rqueue.worker.registry.* settings:

# Persistent state — no TTL
nats kv add rqueue-queue-config      --replicas=3 --storage=file
nats kv add rqueue-message-metadata  --replicas=3 --storage=file

# Job history — match rqueue.message.durability (default 7 days)
nats kv add rqueue-jobs              --replicas=3 --storage=file --ttl=7d

# Locks — cover your longest expected lock hold
nats kv add rqueue-locks             --replicas=3 --storage=file --ttl=10m

# Worker registry — match rqueue.worker.registry.worker.ttl (default 300 s)
nats kv add rqueue-workers           --replicas=3 --storage=file --ttl=5m

# Queue heartbeats — match rqueue.worker.registry.queue.ttl (default 3600 s)
nats kv add rqueue-worker-heartbeats --replicas=3 --storage=file --ttl=1h

KV bucket TTLs are immutable after creation. To change a TTL, delete the bucket and recreate it. Do not delete rqueue-queue-config without backing it up first — it stores all registered queue configurations.


Inspecting Runtime State

Use the nats CLI to inspect what Rqueue has created:

# List all Rqueue streams
nats stream ls | grep rqueue-js-

# Show message counts per queue
nats stream info rqueue-js-orders

# List KV buckets
nats kv ls | grep rqueue-

# Inspect queue configuration
nats kv get rqueue-queue-config orders

Limitations

Feature Redis backend NATS backend
enqueueIn (delayed) Supported Not supported (throws UnsupportedOperationException)
enqueueAt (scheduled) Supported Not supported
enqueuePeriodic (cron) Supported Not supported
priorityGroup weighting Full support Boot warning; weighting not honored
Elastic concurrency (min < max) Supported Falls back to max
@RqueueHandler(primary) Supported Ignored with boot warning
Dashboard charts and message browse Full support Queue sizes only; charts and message browse unavailable
Reactive listener container Supported Enqueue side only