Skip to main content

Default Configs

The transport ships with production-ready defaults for every stream and consumer type. This page lists the exact values from the source code. All defaults can be overridden via module configuration.

Stream Defaults

All streams share a common base configuration:

PropertyValue
retentionWorkqueue (overridden per type below)
storageFile
num_replicas1 (see production recommendation below)
discardOld
allow_directtrue
compressionS2
S2 Compression

All streams default to S2 compression, a Snappy-compatible codec with better ratios. This reduces disk I/O and storage with modest CPU overhead that varies with payload entropy and size. Requires NATS Server >= 2.10 (see runtime requirements). Override per stream kind:

import { StoreCompression } from '@nats-io/jetstream';

events: {
stream: { compression: StoreCompression.None }, // disable for event streams
}

Event Stream

Workqueue retention — each message is removed after being acknowledged by a consumer.

PropertyValueNotes
retentionWorkqueue
storageFile
num_replicas1
allow_rollup_hdrstrue
max_consumers100
max_msg_size10 MB10,485,760 bytes
max_msgs_per_subject5,000,000
max_msgs50,000,000
max_bytes5 GB5,368,709,120 bytes
max_age7 daystoNanos(7, 'days')
duplicate_window2 minutestoNanos(2, 'minutes')
Scheduling

To enable message scheduling, add allow_msg_schedules: true to the event stream config. This requires NATS Server >= 2.12.

Command Stream

Short-lived RPC commands (JetStream RPC mode only).

PropertyValueNotes
retentionWorkqueue
storageFile
num_replicas1
allow_rollup_hdrsfalse
max_consumers50
max_msg_size5 MB5,242,880 bytes
max_msgs_per_subject100,000
max_msgs1,000,000
max_bytes100 MB104,857,600 bytes
max_age3 minutestoNanos(3, 'minutes')
duplicate_window30 secondstoNanos(30, 'seconds')

Broadcast Stream

Limits retention — messages persist until the configured limits are reached. Shared across all services.

PropertyValueNotes
retentionLimits
storageFile
num_replicas1
allow_rollup_hdrstrue
max_consumers200
max_msg_size10 MB10,485,760 bytes
max_msgs_per_subject1,000,000
max_msgs10,000,000
max_bytes2 GB2,147,483,648 bytes
max_age1 hourtoNanos(1, 'hours')
duplicate_window2 minutestoNanos(2, 'minutes')
Changed in v2.9.0

max_age reduced from 1 day to 1 hour. Broadcast messages (config propagation, cache invalidation, feature flags) are relevant for minutes, not days. 1 hour provides sufficient catch-up window for new instances while reducing unnecessary storage. This is a mutable property — existing streams update automatically on next startup.

Ordered Stream

Limits retention for strict sequential delivery. Ordered consumers are ephemeral.

PropertyValueNotes
retentionLimits
storageFile
num_replicas1
allow_rollup_hdrsfalse
max_consumers100
max_msg_size10 MB10,485,760 bytes
max_msgs_per_subject5,000,000
max_msgs50,000,000
max_bytes5 GB5,368,709,120 bytes
max_age1 daytoNanos(1, 'days')
duplicate_window2 minutestoNanos(2, 'minutes')

DLQ Stream

Workqueue retention — dead letters are removed when a DLQ consumer acks them. Created on demand when dlq: { stream } is set in forRoot(). See Dead Letter Queue — Built-in DLQ stream.

PropertyValueNotes
retentionWorkqueue
storageFile
num_replicas1
allow_rollup_hdrsfalse
max_consumers100
max_msg_size10 MB10,485,760 bytes
max_msgs_per_subject5,000,000
max_msgs50,000,000
max_bytes5 GB5,368,709,120 bytes
max_age30 daystoNanos(30, 'days')
duplicate_window2 minutestoNanos(2, 'minutes')

Consumer Defaults

Event Consumer

PropertyValueNotes
ack_wait10 secondstoNanos(10, 'seconds')
max_deliver3Message moves to dead-letter after 3 failed attempts
max_ack_pending100
ack_policyExplicit
deliver_policyAll
replay_policyInstant

Command Consumer

PropertyValueNotes
ack_wait5 minutestoNanos(5, 'minutes')
max_deliver1No retries — RPC failures propagate immediately
max_ack_pending100
ack_policyExplicit
deliver_policyAll
replay_policyInstant

Broadcast Consumer

PropertyValueNotes
ack_wait10 secondstoNanos(10, 'seconds')
max_deliver3
max_ack_pending100
ack_policyExplicit
deliver_policyAll
replay_policyInstant
note

Ordered consumers do not have a durable consumer configuration. They are ephemeral and managed entirely by the @nats-io/jetstream client library.

Connection Defaults

The transport applies the following connection defaults for production resilience:

PropertyValueNotes
maxReconnectAttempts-1Unlimited reconnection attempts
reconnectTimeWait10001 second between reconnection attempts

These defaults ensure the transport automatically recovers from transient network failures without manual intervention. Override them via connectionOptions in forRoot():

JetstreamModule.forRoot({
name: 'orders',
servers: ['nats://localhost:4222'],
connectionOptions: {
maxReconnectAttempts: 10, // limit to 10 attempts
reconnectTimeWait: 2_000, // 2 seconds between attempts
},
})

RPC Timeouts

ModeDefault TimeoutConstant
Core (standard NATS request-reply)30 secondsDEFAULT_RPC_TIMEOUT
JetStream (persistent RPC)3 minutesDEFAULT_JETSTREAM_RPC_TIMEOUT

The JetStream RPC timeout is intentionally longer because messages are persisted to a stream and the consumer may take time to process them.

Graceful Shutdown Timeout

PropertyValue
Shutdown timeout10 seconds

On shutdown, the transport calls drain() on the NATS connection and waits up to 10 seconds for it to complete before forcing the connection closed. Increase this timeout if your handlers have long-running I/O that must finish cleanly.

Replicas in production

The default num_replicas: 1 is suitable for development and single-node NATS. For production NATS clusters, set num_replicas: 3 to ensure data survives node failures via Raft consensus:

JetstreamModule.forRoot({
name: 'orders',
servers: ['nats://nats-1:4222', 'nats://nats-2:4222', 'nats://nats-3:4222'],
events: { stream: { num_replicas: 3 } },
broadcast: { stream: { num_replicas: 3 } },
ordered: { stream: { num_replicas: 3 } },
rpc: { mode: 'jetstream', stream: { num_replicas: 3 } },
});
tip

num_replicas can be changed on an existing stream — NATS will add or remove replicas automatically. No downtime or stream recreation required.

Immutable vs mutable stream properties

NATS JetStream divides stream configuration into properties that can be updated on an existing stream and properties that are locked at creation time.

Mutable (can be changed at any time)

num_replicas, max_age, max_bytes, max_msgs, max_msg_size, max_msgs_per_subject, discard, duplicate_window, subjects, compression, description, allow_rollup_hdrs, allow_direct

The transport applies mutable changes automatically on startup — just update the value in forRoot() and restart the service.

Enable-only (can be turned on, but never off)

These properties can be enabled on an existing stream via a normal update, but once enabled they cannot be disabled. No stream recreation required.

PropertyDefaultNotes
allow_msg_schedulesfalseEnable message scheduling — safe to add to existing streams
allow_msg_ttlfalseEnable per-message TTL
deny_deletefalsePrevent message deletion via API
deny_purgefalsePrevent stream purging via API
Enabling scheduling on existing streams

You can safely add allow_msg_schedules: true to an existing stream config — NATS applies this as a regular update. No downtime, no message loss, no stream recreation. Just update forRoot() and restart.

Immutable (locked after creation)

PropertyDefaultMigratableNotes
namederived from service nameNoCannot be renamed
retentionWorkqueue or LimitsNoControlled by the transport — a mismatch is always an error
storageFileYesCan be migrated with allowDestructiveMigration: true

The transport can automatically migrate storage via blue-green stream recreation. See the full Stream Migration guide for how it works, rolling update behavior, performance benchmarks, and limitations.

retention is never migratable

retention is controlled by the transport (Workqueue for events/commands, Limits for broadcast/ordered). A mismatch between the running stream and the expected retention policy always throws an error on startup, regardless of allowDestructiveMigration.

Overriding Defaults

All stream and consumer defaults can be overridden in forRoot() options. User-provided values are merged on top of the defaults — you only need to specify the properties you want to change.

import { RetentionPolicy, StorageType } from '@nats-io/jetstream';
import { JetstreamModule, toNanos } from '@horizon-republic/nestjs-jetstream';

JetstreamModule.forRoot({
name: 'orders',
servers: ['nats://localhost:4222'],
events: {
stream: {
storage: StorageType.Memory, // override just storage type
max_age: toNanos(3, 'days'), // 3 days instead of 7
},
consumer: {
max_deliver: 5, // 5 retries instead of 3
},
},
rpc: {
mode: 'jetstream',
timeout: 60_000, // 1 minute instead of 3
stream: {
max_msg_size: 1024 * 1024, // 1 MB limit for RPC payloads
},
},
});

See Module Configuration for the full options reference.

Exported constants

Every default above is exposed as a typed constant from the package, so you can import and reuse it when composing overrides programmatically or writing tests.

Stream and consumer defaults:

ConstantContents
DEFAULT_EVENT_STREAM_CONFIGEvent (workqueue) stream defaults
DEFAULT_BROADCAST_STREAM_CONFIGBroadcast stream defaults (shared broadcast-stream)
DEFAULT_ORDERED_STREAM_CONFIGOrdered stream defaults
DEFAULT_COMMAND_STREAM_CONFIGJetStream RPC command stream defaults
DEFAULT_DLQ_STREAM_CONFIGDead Letter Queue stream defaults
DEFAULT_EVENT_CONSUMER_CONFIGEvent consumer defaults
DEFAULT_BROADCAST_CONSUMER_CONFIGBroadcast consumer defaults
DEFAULT_COMMAND_CONSUMER_CONFIGJetStream RPC command consumer defaults

Timeouts:

ConstantValue
DEFAULT_RPC_TIMEOUT30_000 (Core mode timeout, ms)
DEFAULT_JETSTREAM_RPC_TIMEOUT180_000 (JetStream mode timeout, ms)
DEFAULT_SHUTDOWN_TIMEOUT10_000 (graceful shutdown drain timeout, ms)

Handler metadata registry:

ConstantValue
DEFAULT_METADATA_BUCKET'handler_registry'
DEFAULT_METADATA_REPLICAS1
DEFAULT_METADATA_HISTORY1
DEFAULT_METADATA_TTL30_000 (heartbeat-refreshed entry TTL, ms)
MIN_METADATA_TTL5_000 (minimum configurable TTL, ms)

Other:

  • RESERVED_HEADERS — the Set<string> of header names blocked by JetstreamRecordBuilder.setHeader(). See Record Builder.
import { DEFAULT_EVENT_STREAM_CONFIG, toNanos } from '@horizon-republic/nestjs-jetstream';

events: {
stream: { ...DEFAULT_EVENT_STREAM_CONFIG, max_age: toNanos(14, 'days') },
}