NEW: The Edge Autonomy Gap report. AI is arriving at the edge — 500 practitioners say the infrastructure isn't ready.
All posts

A common community question is whether JetStream’s per-stream Raft design can scale when an application has many durable logs, many tenants, or changing cluster capacity.

The short answer: JetStream does use Raft groups at stream granularity, but a stream is not limited to one subject. You can place multiple subjects, including wildcard subject spaces, into a single stream when that matches your data model. When you truly need separate durable logs, separate retention policies, separate placement, or separate operational lifecycles, separate streams are the right abstraction—but they do carry per-stream replication and placement overhead.

Why Raft per stream?

JetStream clustering is built around replicated assets. For streams, the stream has its own replication group rather than being assigned to a fixed global shard set.

That design has a practical tradeoff:

  • Cost: each replicated stream has metadata, placement, leadership, and replication work associated with it.
  • Flexibility: each stream can have its own replica count, placement constraints, subject set, retention policy, and topology.

This is different from systems where all logs are assigned to a fixed shard map. JetStream favors per-stream control over a one-size-fits-all shard topology.

A stream can contain more than one subject

A stream can capture many subjects, so you usually do not need a separate stream for every subject or every event type.

For example, depending on your requirements, a tenant-oriented stream might capture a subject space such as:

1
tenants.123.>

or an application stream might capture related subjects such as:

1
orders.created
2
orders.updated
3
orders.cancelled

That can reduce the number of Raft groups while preserving a single durable log for related data.

However, do not merge streams only to reduce overhead if the semantics are different. Separate streams are still appropriate when you need separate durability, retention, placement, access patterns, data lifecycle, or operational ownership.

How JetStream places stream replicas

When a stream has replicas, JetStream chooses which servers host those replicas. For example, with a five-node JetStream cluster and a stream configured with three replicas, the stream’s Raft group will be placed on three of those servers.

Placement depends on cluster state and stream configuration:

  • If the cluster has more eligible servers than the stream’s replica count, JetStream can distribute streams across available servers.
  • If you do not define placement constraints, JetStream attempts to choose a suitable placement automatically.
  • If you need control over where streams land, you can use placement tags.
  • Stream leaders can move over time or through administrative action.

Placement tags are useful when you need to express topology constraints, such as keeping certain streams on a class of servers, in a location, or within a tenant-specific pool.

What happens when you add nodes?

Adding JetStream servers can be a normal administrative operation, but it is not an automatic rebalance event for existing streams.

In practice:

  • New streams may be placed on the newly added servers.
  • Existing streams do not automatically reshuffle onto those servers just because capacity was added.
  • To use new capacity for existing streams, plan an administrative move or placement change.

This is an important distinction for capacity planning. Adding servers increases the pool of possible placement targets, but it does not by itself migrate existing replicated streams onto those servers.

What happens when you remove nodes?

Removing nodes should be treated as an administrative operation, not as routine autoscaling.

The safest pattern is:

  1. Add or verify enough remaining capacity.
  2. Move stream leaders and replicas away from the server you intend to remove.
  3. Confirm the cluster is healthy.
  4. Explicitly remove the peer from the cluster metadata.
  5. Decommission the server.

These cluster operations—relocating stream leaders and replicas, and removing a peer—are carried out with the NATS CLI. Do not assume that a JetStream server simply disappears from quorum calculations because it has been stopped for some period of time. Removing a peer requires explicit administrative action.

There are cases where removing a replica peer can cause the system to place a replacement replica elsewhere, but relying on that during decommissioning is riskier because it assumes the rest of the cluster remains healthy while the operation completes. For planned maintenance, move first, then remove.

Is JetStream designed for frequent cluster autoscaling?

Not in the sense of frequently adding and removing JetStream servers and expecting automatic reshuffling of existing streams.

Consensus systems are sensitive to membership changes because quorum, replica placement, and leader availability all matter. JetStream clusters can be expanded or contracted, but frequent elastic membership changes are not the recommended operating model.

If your goal is to add and remove capacity dynamically at external sites, edge locations, or tenant-specific environments, consider whether NATS leaf nodes, stream sourcing, or stream mirroring better match the topology. Those tools can help connect locations and move data without treating the core JetStream cluster membership as disposable capacity.

Does the JetStream meta layer route data?

JetStream has cluster metadata that tracks configured streams, consumers, and where those assets are placed. That metadata is used for control-plane decisions.

The data path is different. Subject-interest propagation in core NATS handles message routing. For a stream, the stream leader subscribes to the stream’s subjects at the core NATS layer. Messages published to matching subjects are routed through normal NATS subject routing to the appropriate stream leader.

That means the metadata layer is not in the middle of every published message.

What happens to clients when assets move?

NATS routing is name-based rather than location-based from the client’s point of view. A publisher or consumer normally addresses subjects, not a specific stream replica host.

If a stream leader or replica moves while a client remains connected to a healthy server, the client generally does not need to reconnect just because the asset moved. The cluster routes based on subject interest.

A reconnect is needed if the client is directly connected to a server that is being shut down or removed. This is one reason production clients should be configured with multiple server URLs and normal reconnect behavior.

Multi-tenant considerations

For multi-tenant deployments, the main design question is usually not only how many streams JetStream can hold, but how tenant isolation maps to stream semantics and placement.

Consider:

  • Can each tenant use one or a small number of streams with subject partitions inside the stream?
  • Do tenants require separate retention or placement policies?
  • Are there noisy-neighbor concerns that require separate accounts, placement tags, or server pools?
  • Are some streams expected to be much hotter than others?
  • Do you need data locality across zones or regions?

In NATS 2.11 and later, there is also support for moving Raft replication traffic out of the system account and into the account where the replicated asset belongs. Paired with route pooling, that can help reduce head-of-line blocking between accounts in multi-tenant-style deployments. Treat this as an architectural tuning option rather than a substitute for stream and capacity design.

How to think about very high-throughput logs

If one stream represents one durable append-only log, then all writes for that log are coordinated through that stream’s replication group. Batching can help, but the achievable throughput and latency depend on the full environment: payload size, storage, network latency, replica count, acknowledgment pattern, consumers, and tail latency across availability zones.

For targets such as high append rates, low quorum latency, and hundreds or thousands of concurrent consumers, benchmark the exact shape you intend to run. In particular, test:

  • The chosen replica count.
  • Same-zone versus cross-zone latency.
  • Payload sizes and batch sizes.
  • Storage configuration.
  • Consumer fanout and acknowledgment behavior.
  • Failure and maintenance scenarios, not only steady state.

Public case studies can provide useful context, but they cannot replace a workload-specific test for your durability, latency, and fanout requirements.

Practical guidance

Use fewer streams when one stream can correctly model a related subject space. Use more streams when you need separate durable logs, policies, placement, or lifecycle boundaries.

For clustered JetStream operations:

  • Plan cluster membership to be relatively stable.
  • Use placement tags when placement matters.
  • Expect new streams, not existing streams, to take advantage of newly added nodes automatically.
  • Move replicas and leaders before planned node removal.
  • Use explicit peer-removal procedures when decommissioning servers.
  • Rely on core NATS subject routing for data movement, not client knowledge of stream placement.

JetStream’s per-stream Raft design is a deliberate tradeoff: it adds per-stream overhead, but it gives fine-grained control over replication, placement, and topology. The right architecture depends on how your durable logs map to streams and how much operational flexibility you need.


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