SLVZ.RateLimiter 1.0.2

dotnet add package SLVZ.RateLimiter --version 1.0.2
                    
NuGet\Install-Package SLVZ.RateLimiter -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SLVZ.RateLimiter" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SLVZ.RateLimiter" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="SLVZ.RateLimiter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SLVZ.RateLimiter --version 1.0.2
                    
#r "nuget: SLVZ.RateLimiter, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SLVZ.RateLimiter@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SLVZ.RateLimiter&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=SLVZ.RateLimiter&version=1.0.2
                    
Install as a Cake Tool

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 true when the operation is allowed; otherwise false.

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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.

Version Downloads Last Updated
1.0.2 98 8/27/2026
1.0.1 88 8/21/2026
1.0.0 95 8/20/2026