SLVZ.RateLimiter
1.0.2
dotnet add package SLVZ.RateLimiter --version 1.0.2
NuGet\Install-Package SLVZ.RateLimiter -Version 1.0.2
<PackageReference Include="SLVZ.RateLimiter" Version="1.0.2" />
<PackageVersion Include="SLVZ.RateLimiter" Version="1.0.2" />
<PackageReference Include="SLVZ.RateLimiter" />
paket add SLVZ.RateLimiter --version 1.0.2
#r "nuget: SLVZ.RateLimiter, 1.0.2"
#:package SLVZ.RateLimiter@1.0.2
#addin nuget:?package=SLVZ.RateLimiter&version=1.0.2
#tool nuget:?package=SLVZ.RateLimiter&version=1.0.2
SLVZ.RateLimiter
A lightweight, thread-safe, in-memory rate limiter for .NET with per-key limits and configurable expiration windows.
Features
- Thread-safe
- Per-key rate limiting
- Supports any key type through
object - Configurable request limit
- Configurable time window for each key
- Automatic background cleanup of expired entries
- Designed for high-volume workloads
- No external dependencies
Installation
Add the project to your solution or install the NuGet package when available.
Usage
Initialize the cleanup timer once when the application starts:
RateLimiter.Initialize();
The cleanup interval can be customized:
RateLimiter.Initialize(TimeSpan.FromSeconds(30));
Initialize controls how often expired entries are cleaned up. It does not determine how long a rate-limit window lasts.
Use Allow to check whether an operation is permitted:
if (!RateLimiter.Allow(
"user:123",
limit: 5,
duration: TimeSpan.FromMinutes(1)))
{
// Rate limit exceeded
}
Different values are tracked independently:
RateLimiter.Allow("user:123", 5, TimeSpan.FromMinutes(1));
RateLimiter.Allow(12345, 10, TimeSpan.FromSeconds(30));
RateLimiter.Allow(Guid.NewGuid(), 3, TimeSpan.FromMinutes(5));
Keys should be immutable. The key's Equals and GetHashCode implementations are used to identify entries.
API
Initialize
RateLimiter.Initialize(TimeSpan? cleanUpDuration = null);
Starts the background cleanup timer.
cleanUpDuration: interval between cleanup operations.- Default:
1 minute.
Allow
bool RateLimiter.Allow(
object key,
int limit,
TimeSpan duration);
Determines whether the specified key is allowed to perform an operation within its configured rate limit.
key: value used to identify the rate-limit entry.limit: maximum number of operations allowed during the window.duration: length of the rate-limit window.- Returns
truewhen the operation is allowed; otherwisefalse.
Example: Login Protection
if (!RateLimiter.Allow(
$"login:{username}",
limit: 5,
duration: TimeSpan.FromMinutes(5)))
{
return Results.StatusCode(StatusCodes.Status429TooManyRequests);
}
Thread Safety
The limiter is designed for concurrent access.
Each key maintains its own state, so contention is localized to the corresponding entry rather than a single global lock.
Cleanup
Expired entries are removed automatically by a background timer.
The cleanup process does not need to scan every active entry on each run. Expiration information is ordered so that cleanup can process expired entries and stop as soon as it reaches an entry that has not expired yet.
Performance
Benchmarks were performed with BenchmarkDotNet on:
- CPU: Intel Core i7-1065G7
- Cores: 4 physical / 8 logical
- Runtime: .NET 10.0.8
- OS: Windows 11
- Key count: 1,000,000
- Operation count: 1,000,000
Sequential
| Benchmark | Mean | Allocated |
|---|---|---|
AllowExistingKeys |
150.1 ms | 38.15 MB |
AllowNewKeys |
188.1 ms | 91.48 MB |
Concurrent
| Benchmark | Mean | Allocated |
|---|---|---|
ConcurrentSharedKeys |
44.29 ms | 38.16 MB |
ConcurrentUniqueKeys |
51.85 ms | 38.15 MB |
The concurrent shared-key benchmark used 1,000,000 operations distributed across 100 keys, creating contention on individual entries.
Benchmark results depend on hardware, runtime version, operating-system state, and benchmark configuration. Run the included benchmarks on your own environment before making performance assumptions.
Limitations
This is an in-memory rate limiter.
It is appropriate for a single application process. In a multi-instance or distributed deployment, each application instance maintains its own independent state.
For distributed rate limiting across multiple servers or containers, use a distributed state store or a distributed rate-limiting solution.
👨💻 Author: SLVZ
| 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
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.