Innovabit.DotNet.Interceptors.RateLimiting.Abstractions
2.0.115
dotnet add package Innovabit.DotNet.Interceptors.RateLimiting.Abstractions --version 2.0.115
NuGet\Install-Package Innovabit.DotNet.Interceptors.RateLimiting.Abstractions -Version 2.0.115
<PackageReference Include="Innovabit.DotNet.Interceptors.RateLimiting.Abstractions" Version="2.0.115" />
<PackageVersion Include="Innovabit.DotNet.Interceptors.RateLimiting.Abstractions" Version="2.0.115" />
<PackageReference Include="Innovabit.DotNet.Interceptors.RateLimiting.Abstractions" />
paket add Innovabit.DotNet.Interceptors.RateLimiting.Abstractions --version 2.0.115
#r "nuget: Innovabit.DotNet.Interceptors.RateLimiting.Abstractions, 2.0.115"
#:package Innovabit.DotNet.Interceptors.RateLimiting.Abstractions@2.0.115
#addin nuget:?package=Innovabit.DotNet.Interceptors.RateLimiting.Abstractions&version=2.0.115
#tool nuget:?package=Innovabit.DotNet.Interceptors.RateLimiting.Abstractions&version=2.0.115
Innovabit.DotNet.Interceptors.RateLimiting.Abstractions
Per-method rate limiting for Innovabit.DotNet.Interceptors
via a [RateLimit] attribute. This is the provider-agnostic base: it ships the interceptor, the
attribute and the IRateLimiterStore abstraction. Pick a store to keep the allowances:
Innovabit.DotNet.Interceptors.RateLimiting.Memory— in this process.Innovabit.DotNet.Interceptors.RateLimiting.Redis— shared across every instance.
Usage
services
.AddInterceptors()
.AddInMemoryRateLimiter(); // or .AddRedisRateLimiter()
services.AddScopedWithInterception<IQuoteService, QuoteService>();
public class QuoteService : IQuoteService
{
// 100 calls a minute, per tenant.
[RateLimit(PermitLimit = 100, WindowSeconds = 60, PartitionBy = "tenantId")]
public Task<Quote> GetAsync(string tenantId, string symbol, CancellationToken cancellationToken) { ... }
}
A call that does not fit throws RateLimitExceededException without reaching the method, so
nothing was attempted and it is always safe to retry. The exception carries RetryAfter, ready for
an HTTP Retry-After header or a broker's delay.
[RateLimit]
| Property | Meaning |
|---|---|
PermitLimit |
Calls allowed per window. Defaults to 100. |
WindowSeconds |
Length of the window. Defaults to 60. |
PartitionBy |
Name of a parameter whose value splits the allowance, so each value is limited on its own. Unset = one allowance for the whole method. |
Name |
Name the allowance is stored under. Give two methods the same name to have them share one quota. |
Partition by something that identifies the caller, not the request. A value with unbounded cardinality — a search term, a request id — would create an allowance per call: it would limit nothing and grow the store forever.
Partition values are rendered with the invariant culture, so the same tenant cannot end up in two allowances depending on the culture of the thread that served the call.
Misconfiguration fails loudly
A PartitionBy that matches no parameter throws, naming the parameters that do exist, instead of
quietly falling back to a global allowance — that mistake only shows up once the quota is already
doing the wrong thing. A PermitLimit or WindowSeconds of zero or less throws for the same reason.
Ordering
The interceptor runs at InterceptorOrders.RateLimit (60), near the outside:
- A throttled caller spends nothing — no authorization lookup, no validation, no cache read.
- It is inside auditing (50), so the refused attempt is still recorded.
- It is outside notifications (300), so being throttled does not page anyone.
Using [RateLimit] the other way round — to throttle calls your service makes to a metered
dependency — wants the opposite position, near the circuit breaker. Move it per registration:
services.AddInterceptors()
.AddInMemoryRateLimiter()
.SetOrder<RateLimitInterceptor>(InterceptorOrders.CircuitBreaker - 10);
Writing a store
public sealed class MyStore : IRateLimiterStore
{
public ValueTask<RateLimitDecision> TryAcquireAsync(
string partitionKey, RateLimitPolicy policy, CancellationToken cancellationToken = default) { ... }
}
services.AddInterceptors().AddRateLimiterStore<MyStore>();
Document what your store does when it cannot answer. The bundled ones let the call through: a rate limiter exists to protect you from too much traffic, and taking the service down because the limiter is unavailable trades a degraded service for no service at all.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.115)
-
net8.0
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.115)
-
net9.0
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.115)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Innovabit.DotNet.Interceptors.RateLimiting.Abstractions:
| Package | Downloads |
|---|---|
|
Innovabit.DotNet.Interceptors.RateLimiting.Redis
Redis rate limiter store for interceptor-based [RateLimit] methods, shared across instances. |
|
|
Innovabit.DotNet.Interceptors.All
Meta-package: every interceptor concern in the suite (logging, validation, caching, notifications, telemetry, audit, authorization, rate limiting, coordination, feature gates, transactions, retry/timeout/circuit breaker/fallback) in one reference. Providers are separate packages — pick the ones you use. |
|
|
Innovabit.DotNet.Interceptors.RateLimiting.Memory
In-process rate limiter store for interceptor-based [RateLimit] methods. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.115 | 135 | 10/17/2026 |
| 2.0.114 | 135 | 10/10/2026 |
| 2.0.113 | 150 | 10/3/2026 |
| 2.0.112 | 150 | 9/28/2026 |
| 2.0.111 | 143 | 9/28/2026 |
| 2.0.110 | 146 | 9/27/2026 |
| 2.0.109 | 145 | 9/26/2026 |
| 2.0.108 | 147 | 9/26/2026 |
| 2.0.107 | 150 | 9/26/2026 |
| 2.0.106 | 150 | 9/25/2026 |
| 2.0.105 | 146 | 9/25/2026 |
| 1.0.0.104 | 126 | 9/25/2026 |
| 1.0.0.103 | 121 | 9/25/2026 |