Skip to content

Native Ingress Rate Limiting for JetStream Stream #7591

@willyaako

Description

@willyaako

Proposed change

I propose adding an optional configuration to StreamConfig to limit the ingress message rate (messages per second) at the individual stream level.

Specific changes:

API Update: Extend StreamConfig struct to include a new field, e.g., MaxMsgsPerSecond (int64). The default value would be 0 (unlimited) to ensure backward compatibility.

Implementation:

Initialize a rate limiter (token bucket) when a Stream is created or updated if the limit is set.

In the stream's write path (likely within processJetStreamMsg in server/stream.go), check this limiter before storing the message.

Behavior on Limit:

If the rate limit is exceeded, the server should reject the message.

For JetStream API publishes, return a specific error (e.g., 503 Service Unavailable or a dedicated 429 equivalent).

For core NATS publishes, the message would be dropped (consistent with standard NATS fire-and-forget behavior when resources are unavailable).

Observability: Expose metrics via /jsz to track the count of messages rejected due to rate limiting.

Use case

Motivation: Multi-tenancy and Resource Protection (The "Noisy Neighbor" Problem)

Currently, JetStream provides flow control for Consumers (MaxAckPending), but lacks a native mechanism to control the write rate of Producers targeting a specific stream.

Scenario: In a shared NATS cluster serving multiple tenants or services, a single misconfigured or malicious producer can flood a stream with an extremely high volume of messages.

Problem: Even with MaxBytes/MaxMsgs retention policies, a high ingress rate causes excessive Disk I/O and memory pressure, potentially degrading the performance of the entire JetStream server and affecting other well-behaved streams.

Why current solutions are insufficient:

Client-side throttling: Cannot be enforced on untrusted or malicious clients.

Sidecar Proxy: Introducing a proxy solely for rate limiting adds significant network latency and operational complexity, negating NATS's low-latency advantage.

This feature would allow operators to strictly enforce quotas (e.g., "Stream A can only accept 1,000 msg/s") directly within the server, ensuring stability in multi-tenant environments.

Contribution

Yes, I am interested in contributing code for this proposal.

I have reviewed the server/stream.go and StreamConfig structures and have a general idea of how to implement the rate-limiting logic within the processJetStreamMsg flow. I would like to get feedback or approval on the design before submitting a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalEnhancement idea or proposal

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions