-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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.