Wiaoj.RateLimiting
0.0.1-alpha.99-preview
dotnet add package Wiaoj.RateLimiting --version 0.0.1-alpha.99-preview
NuGet\Install-Package Wiaoj.RateLimiting -Version 0.0.1-alpha.99-preview
<PackageReference Include="Wiaoj.RateLimiting" Version="0.0.1-alpha.99-preview" />
<PackageVersion Include="Wiaoj.RateLimiting" Version="0.0.1-alpha.99-preview" />
<PackageReference Include="Wiaoj.RateLimiting" />
paket add Wiaoj.RateLimiting --version 0.0.1-alpha.99-preview
#r "nuget: Wiaoj.RateLimiting, 0.0.1-alpha.99-preview"
#:package Wiaoj.RateLimiting@0.0.1-alpha.99-preview
#addin nuget:?package=Wiaoj.RateLimiting&version=0.0.1-alpha.99-preview&prerelease
#tool nuget:?package=Wiaoj.RateLimiting&version=0.0.1-alpha.99-preview&prerelease
Wiaoj.RateLimiting
Core execution runtime, algorithms, policy orchestration, and resilience decorators for the Wiaoj.RateLimiting library.
This package contains the concrete rate limiting algorithm engines, policy registration builders, in-memory state stores, distributed coordination via Wiaoj.DistributedCounter, and OpenTelemetry diagnostics.
Installation
dotnet add package Wiaoj.RateLimiting
Included Algorithms
1. FixedWindowRateLimiter (Distributed / Storage-Backed)
- Counts operations against a fixed time window using
IDistributedCounter.TryIncrementAsync. - Operates atomically in a single round-trip against the configured storage backend (Redis Lua script or In-Memory CAS).
2. SlidingWindowRateLimiter (Distributed / Storage-Backed)
- Approximates a sliding lookback window by blending the previous window's count with the current window based on elapsed time weight.
- Speculatively increments the current counter and executes a rollback decrement if the estimated total exceeds the limit.
3. GcraRateLimiter (Distributed / Storage-Backed)
- Implements the Generic Cell Rate Algorithm (GCRA) by tracking a single Theoretical Arrival Time (TAT) in UTC ticks.
- Executes an optimistic Compare-And-Swap (CAS) retry loop via
IDistributedCounter.TryCompareExchangeAsyncto ensure atomicity across multi-node clusters.
4. TokenBucketRateLimiter (In-Memory)
- Tracks token capacity and continuous refill rate in local memory using
ConcurrentDictionaryand atomic CAS updates. - Absorbs sudden bursts up to capacity, then throttles to the steady refill rate.
5. SlidingWindowLogRateLimiter (In-Memory)
- Maintains an in-memory timestamp log per key, evicting expired entries on each acquisition.
- Guarantees exact rolling lookback evaluation with no window boundary burst anomalies.
6. LeakyBucketQueueRateLimiter (In-Memory / Traffic Shaping)
- A traffic shaper that holds admitted requests inside
TryAcquireAsyncusingTimeProvider.Delayuntil their scheduled turn arrives. - Rejects requests immediately only when the maximum queue backlog capacity is exceeded.
- Automatically rolls back backlog reservations if the caller's
CancellationTokenis triggered during wait.
7. CompositeRateLimiter
- Evaluates an ordered sequence of algorithm tiers.
- A request is permitted only if all configured tiers allow it. Returns the minimum remaining capacity among allowing tiers, or the maximum
RetryAfterif any tier denies.
Dependency Injection Setup
Configuring Named and Typed Policies
using Wiaoj.DistributedCounter;
using Wiaoj.RateLimiting;
using Wiaoj.RateLimiting.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// 1. Configure underlying counter backend
builder.Services.AddDistributedCounter(dc => dc.UseInMemory());
// 2. Configure rate limiting policies
builder.Services.AddWiaojRateLimiting(limiter => {
// Named policy: Fixed window for auth
limiter.AddPolicy("auth", policy => {
policy.UseFixedWindow(limit: 5, window: TimeSpan.FromMinutes(1))
.WithFailOpen();
});
// Named policy: Burst-tolerant GCRA for searches
limiter.AddPolicy("search", policy => {
policy.UseGcra(limit: 20, period: TimeSpan.FromSeconds(1))
.WithNegativeCaching();
});
// Strongly-typed policy for payments
limiter.AddPolicy<PaymentPolicy>(policy => {
policy.UseTokenBucket(capacity: 10, window: TimeSpan.FromMinutes(1));
});
// Multi-tier composite policy
limiter.AddPolicy("tiered_api", policy => {
policy.UseComposite(
tier1 => tier1.UseFixedWindow(limit: 10, window: TimeSpan.FromSeconds(1)),
tier2 => tier2.UseSlidingWindow(limit: 1000, window: TimeSpan.FromHours(1))
);
});
// Default fallback policy
limiter.UseDefaultPolicy(policy => {
policy.UseFixedWindow(limit: 100, window: TimeSpan.FromMinutes(1));
});
});
Per-Policy Storage Routing
By default, distributed algorithms (FixedWindow, SlidingWindow, Gcra) route counter operations to the global storage configured in AddDistributedCounter.
Specific policies can be routed to dedicated storage instances, keyed Redis multiplexers, or custom database backends directly within the policy builder:
builder.Services.AddWiaojRateLimiting(limiter => {
// Route authentication rate limiting to an isolated storage
limiter.AddPolicy("auth", policy => {
policy.UseFixedWindow(limit: 5, window: TimeSpan.FromMinutes(1))
.UseKeyedStorage("security-redis")
.WithFailOpen();
});
// Route billing rate limiting to a custom database backend
limiter.AddPolicy("billing", policy => {
policy.UseGcra(limit: 100, period: TimeSpan.FromHours(1))
.UseStorage<PostgresCounterStorage>();
});
});
Resilience Decorators
Decorators can be chained onto any policy in the builder:
WithFailOpen() (ResilientRateLimiter)
Catches storage and network exceptions thrown by the underlying storage backend and allows the request through with RateLimitDecision.Allowed(), logging an error to prevent API outages during infrastructure downtime. Cancellation exceptions are preserved and rethrown.
WithNegativeCaching() (NegativeCacheRateLimiter)
Remembers denied keys in an in-memory ConcurrentDictionary for the duration of their RetryAfter window. Subsequent requests during the penalty period are rejected immediately in local RAM without making network round-trips to remote storage.
Observability
OpenTelemetry Metrics (Wiaoj.RateLimiting)
Subscribe to the meter in OpenTelemetry configuration:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => {
metrics.AddMeter("Wiaoj.RateLimiting");
});
rate_limit.decisions(Counter<long>): Number of decisions evaluated, tagged withrate_limit.policy,rate_limit.algorithmandrate_limit.decision(allowed/denied).rate_limit.cost.consumed(Counter<long>): Total units consumed by permitted requests, tagged withrate_limit.policyandrate_limit.algorithm.rate_limit.queue.wait_duration(Histogram<double>inms): Time requests spent suspended inLeakyBucketQueueRateLimiter.
Tracing (Wiaoj.RateLimiting)
IRateLimiter.TryAcquireAsync emits a rate_limit.acquire span tagged with rate_limit.policy, rate_limit.key, rate_limit.cost, rate_limit.decision, rate_limit.remaining, and rate_limit.retry_after_ms when denied.
A denial is deliberately not an Error status: exceeding a quota is the limiter working as designed and is returned as a value rather than thrown, so the operation did not fail. StartActivity returns null when nothing is subscribed, so tracing costs nothing until a listener is attached.
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing.AddSource("Wiaoj.RateLimiting"));
Logging
Source-generated structured log messages are emitted under the Wiaoj.RateLimiting category for decision outcomes, queue delays, speculative rollbacks, and storage failure fallbacks.
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.2)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.2)
- Microsoft.Extensions.Options (>= 10.0.2)
- Wiaoj.DistributedCounter (>= 0.0.1-alpha.99-preview)
- Wiaoj.DistributedCounter.Abstractions (>= 0.0.1-alpha.99-preview)
- Wiaoj.Extensions (>= 0.0.1-alpha.99-preview)
- Wiaoj.Preconditions (>= 0.0.1-alpha.99-preview)
- Wiaoj.Primitives (>= 0.0.1-alpha.99-preview)
- Wiaoj.RateLimiting.Abstractions (>= 0.0.1-alpha.99-preview)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Wiaoj.RateLimiting:
| Package | Downloads |
|---|---|
|
Wiaoj.RateLimiting.AspNetCore
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-alpha.99-preview | 61 | 9/6/2026 |
| 0.0.1-alpha.98-preview | 61 | 9/6/2026 |
| 0.0.1-alpha.97-preview | 56 | 9/6/2026 |
| 0.0.1-alpha.96-preview | 53 | 9/6/2026 |
| 0.0.1-alpha.95-preview | 62 | 9/6/2026 |
| 0.0.1-alpha.108-preview | 51 | 9/8/2026 |
| 0.0.1-alpha.107-preview | 60 | 9/8/2026 |
| 0.0.1-alpha.106-preview | 46 | 9/8/2026 |
| 0.0.1-alpha.105-preview | 45 | 9/8/2026 |
| 0.0.1-alpha.104-preview | 67 | 9/7/2026 |
| 0.0.1-alpha.103-preview | 50 | 9/7/2026 |
| 0.0.1-alpha.102-preview | 63 | 9/6/2026 |
| 0.0.1-alpha.101-preview | 66 | 9/6/2026 |
| 0.0.1-alpha.100-preview | 54 | 9/6/2026 |