Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nimanikoo/Dotnet-RateLimiter/llms.txt
Use this file to discover all available pages before exploring further.
RateLimiterExtensions provides a single AddCustomRateLimiter extension method on IServiceCollection that consolidates every service registration the application needs: the Redis connection, the RedisRateLimiter singleton, four built-in ASP.NET Core rate-limiting policies, health checks with a Redis probe and a UI, and Swagger. Calling this one method in Program.cs replaces a large block of repetitive setup code and keeps the startup entry point concise.
Namespace
namespace Dotnet_RateLimiter.Extensions;
Method: AddCustomRateLimiter
public static IServiceCollection AddCustomRateLimiter(
this IServiceCollection services,
IConfiguration configuration)
Returns: IServiceCollection — the same services instance, enabling fluent chaining.
services
IServiceCollection
required
The service collection to register all dependencies into. Passed implicitly as the
extension target (i.e. builder.Services).
The application configuration object. The method reads the Redis connection string from
the key Redis:ConnectionString. If the key is absent it falls back to
"localhost:6379".
What It Registers
Full Source
public static IServiceCollection AddCustomRateLimiter(this IServiceCollection services,
IConfiguration configuration)
{
var redisConnectionString = configuration.GetSection("Redis:ConnectionString").Value
?? "localhost:6379";
var redis = ConnectionMultiplexer.Connect(redisConnectionString);
services.AddSingleton<IConnectionMultiplexer>(redis);
services.AddHealthChecks()
.AddRedis(
redisConnectionString: configuration.GetSection("Redis:ConnectionString").Value!,
name: "Redis Server",
tags: ["db", "cache", "redis"]
);
services.AddHealthChecksUI(settings =>
{
settings.AddHealthCheckEndpoint("Main App", "http://localhost:8080/health");
settings.SetEvaluationTimeInSeconds(5);
}).AddInMemoryStorage();
services.AddSingleton<RedisRateLimiter>();
services.AddControllers();
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("FixedWindowPolicy", opt =>
{
opt.Window = TimeSpan.FromSeconds(5);
opt.PermitLimit = 5;
opt.QueueLimit = 10;
//LIFO approach : Last in First out
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
}).RejectionStatusCode = 429;
options.AddSlidingWindowLimiter("SlidingWindowPolicy", opt =>
{
opt.Window = TimeSpan.FromSeconds(10);
opt.PermitLimit = 5;
opt.QueueLimit = 10;
//LIFO approach : Last in First out
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.SegmentsPerWindow = 4;
}).RejectionStatusCode = 429;
options.AddConcurrencyLimiter("ConcurrencyPolicy", opt =>
{
opt.PermitLimit = 7;
opt.QueueLimit = 3;
//LIFO approach : Last in First out
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
}).RejectionStatusCode = 429;
options.AddTokenBucketLimiter("BucketPolicy", opt =>
{
opt.TokenLimit = 5;
opt.QueueLimit = 2;
//LIFO approach : Last in First out
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.ReplenishmentPeriod = TimeSpan.FromSeconds(5);
opt.AutoReplenishment = true;
opt.TokensPerPeriod = 3;
}).RejectionStatusCode = 429;
});
return services;
}
Registration Breakdown
1. IConnectionMultiplexer — Redis Connection
var redisConnectionString = configuration.GetSection("Redis:ConnectionString").Value
?? "localhost:6379";
var redis = ConnectionMultiplexer.Connect(redisConnectionString);
services.AddSingleton<IConnectionMultiplexer>(redis);
Creates and registers a StackExchange.Redis ConnectionMultiplexer as a singleton using
the connection string from configuration. Falls back to localhost:6379 if the config
key is not present.
Required appsettings.json key:
{
"Redis": {
"ConnectionString": "localhost:6379"
}
}
2. Health Checks — Redis Probe
services.AddHealthChecks()
.AddRedis(
redisConnectionString: configuration.GetSection("Redis:ConnectionString").Value!,
name: "Redis Server",
tags: ["db", "cache", "redis"]
);
Adds the AspNetCore.HealthChecks.Redis probe. The health check endpoint is mapped in
Program.cs at /health using UIResponseWriter.WriteHealthCheckUIResponse.
| Property | Value |
|---|
| Name | Redis Server |
| Tags | db, cache, redis |
| Endpoint (Program.cs) | /health |
3. Health Checks UI — InMemory Storage
services.AddHealthChecksUI(settings =>
{
settings.AddHealthCheckEndpoint("Main App", "http://localhost:8080/health");
settings.SetEvaluationTimeInSeconds(5);
}).AddInMemoryStorage();
Registers the HealthChecks UI dashboard with in-memory storage. The UI polls the
/health endpoint every 5 seconds.
| Property | Value |
|---|
| Monitored endpoint | http://localhost:8080/health |
| Poll interval | 5 seconds |
| Storage | In-memory |
| UI path (Program.cs) | /health-ui |
4. RedisRateLimiter Singleton
services.AddSingleton<RedisRateLimiter>();
Registers the core distributed rate-limiter service. See
RedisRateLimiter for full details.
5. Controllers, API Explorer, and SwaggerGen
services.AddControllers();
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
Standard registrations for MVC controllers and the Swagger/OpenAPI document generator.
UseSwagger() and UseSwaggerUI() are called in Program.cs in the development
environment.
6. Rate Limiting Policies
Four named policies are registered via services.AddRateLimiter(...). All four use
QueueProcessingOrder.OldestFirst and return 429 on rejection.
FixedWindowPolicy
options.AddFixedWindowLimiter("FixedWindowPolicy", opt =>
{
opt.Window = TimeSpan.FromSeconds(5);
opt.PermitLimit = 5;
opt.QueueLimit = 10;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
}).RejectionStatusCode = 429;
| Property | Value |
|---|
| Window | 5 seconds |
| PermitLimit | 5 requests |
| QueueLimit | 10 requests |
| QueueProcessingOrder | OldestFirst |
| Rejection status | 429 |
SlidingWindowPolicy
options.AddSlidingWindowLimiter("SlidingWindowPolicy", opt =>
{
opt.Window = TimeSpan.FromSeconds(10);
opt.PermitLimit = 5;
opt.QueueLimit = 10;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.SegmentsPerWindow = 4;
}).RejectionStatusCode = 429;
| Property | Value |
|---|
| Window | 10 seconds |
| PermitLimit | 5 requests |
| QueueLimit | 10 requests |
| SegmentsPerWindow | 4 |
| QueueProcessingOrder | OldestFirst |
| Rejection status | 429 |
ConcurrencyPolicy
options.AddConcurrencyLimiter("ConcurrencyPolicy", opt =>
{
opt.PermitLimit = 7;
opt.QueueLimit = 3;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
}).RejectionStatusCode = 429;
| Property | Value |
|---|
| PermitLimit | 7 concurrent requests |
| QueueLimit | 3 requests |
| QueueProcessingOrder | OldestFirst |
| Rejection status | 429 |
BucketPolicy
options.AddTokenBucketLimiter("BucketPolicy", opt =>
{
opt.TokenLimit = 5;
opt.QueueLimit = 2;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.ReplenishmentPeriod = TimeSpan.FromSeconds(5);
opt.AutoReplenishment = true;
opt.TokensPerPeriod = 3;
}).RejectionStatusCode = 429;
| Property | Value |
|---|
| TokenLimit | 5 tokens (bucket capacity) |
| QueueLimit | 2 requests |
| ReplenishmentPeriod | 5 seconds |
| TokensPerPeriod | 3 tokens added per period |
| AutoReplenishment | true |
| QueueProcessingOrder | OldestFirst |
| Rejection status | 429 |
Usage
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCustomRateLimiter(builder.Configuration);
var app = builder.Build();
Because the method returns IServiceCollection you can chain additional registrations:
builder.Services
.AddCustomRateLimiter(builder.Configuration)
.AddSingleton<IMyService, MyService>();