Repository navigation
Rate Limiting
thnak edited this page Jun 6, 2026
·
1 revision
MqttControllerFramework includes a token-bucket rate limiter that enforces per-client, per-route message limits. Apply [TokenBucketRateLimit] to any topic handler and call .WithRateLimiting() on the builder.
builder.Services
.AddMqttServer(configuration)
.WithControllers<GeneratedMqttControllerRegistration>()
.WithAuthentication<MyAuthProvider>()
.WithRateLimiting(); // ← registers the rate limit service[TokenBucketRateLimit(capacity, refillRate, refillIntervalMs)]| Parameter | Type | Description |
|---|---|---|
capacity |
int |
Maximum tokens in the bucket (burst limit) |
refillRate |
int |
Tokens added per refill interval |
refillIntervalMs |
int |
Refill interval in milliseconds |
TokensPerRequest |
int |
Tokens consumed per message (default: 1) |
[MqttController]
public class TelemetryController
{
[MqttTopic("telemetry/+/data")]
[TokenBucketRateLimit(capacity: 10, refillRate: 10, refillIntervalMs: 1000)]
public Task OnData([FromMqttTopic(1)] string deviceId, SensorData data) { ... }
}Token bucket behaviour:
- Bucket starts full (
capacitytokens). - Each incoming message consumes
TokensPerRequesttokens. - Tokens refill at
refillRateperrefillIntervalMs. - If the bucket is empty the message is dropped (not queued).
[MqttTopic("bulk/+/import")]
[TokenBucketRateLimit(capacity: 50, refillRate: 10, refillIntervalMs: 1000, TokensPerRequest = 5)]
public Task OnBulkImport([FromMqttTopic(1)] string deviceId, BulkPayload payload) { ... }Multiple attributes can be applied to the same method (e.g. a burst limit and a sustained limit):
[MqttTopic("commands/+/execute")]
[TokenBucketRateLimit(capacity: 5, refillRate: 5, refillIntervalMs: 1000, Name = "burst")]
[TokenBucketRateLimit(capacity: 60, refillRate: 60, refillIntervalMs: 60000, Name = "sustained")]
public Task OnExecute([FromMqttTopic(1)] string deviceId, Command cmd) { ... }By default the rate limit applies per ClientId + route. Each connecting client gets its own token bucket for each rate-limited route.
Implement IRateLimitStrategy and create a custom attribute that inherits RateLimitAttribute to add strategies beyond the built-in token bucket:
public sealed class SlidingWindowRateLimitAttribute(int windowMs, int maxRequests)
: RateLimitAttribute
{
public override string StrategyType => "SlidingWindow";
public override bool ValidateConfiguration() => windowMs > 0 && maxRequests > 0;
public override Dictionary<string, object> GetConfiguration() => new()
{
["WindowMs"] = windowMs,
["MaxRequests"] = maxRequests
};
}Then implement IRateLimitStrategy and register it with the DI container.
- Rate limiting is enforced by the generated routing service before the controller dispatcher runs.
- Messages dropped by the rate limiter are counted in
IMqttBrokerStatsService.GetDroppedMessageCount(). -
TokensPerRequestmust be> 0and<= capacity— an invalid configuration is detected at build time viaValidateConfiguration().