Skip to main content

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).
configuration
IConfiguration
required
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.
PropertyValue
NameRedis Server
Tagsdb, 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.
PropertyValue
Monitored endpointhttp://localhost:8080/health
Poll interval5 seconds
StorageIn-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;
PropertyValue
Window5 seconds
PermitLimit5 requests
QueueLimit10 requests
QueueProcessingOrderOldestFirst
Rejection status429

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;
PropertyValue
Window10 seconds
PermitLimit5 requests
QueueLimit10 requests
SegmentsPerWindow4
QueueProcessingOrderOldestFirst
Rejection status429

ConcurrencyPolicy
options.AddConcurrencyLimiter("ConcurrencyPolicy", opt =>
{
    opt.PermitLimit = 7;
    opt.QueueLimit = 3;
    opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
}).RejectionStatusCode = 429;
PropertyValue
PermitLimit7 concurrent requests
QueueLimit3 requests
QueueProcessingOrderOldestFirst
Rejection status429

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;
PropertyValue
TokenLimit5 tokens (bucket capacity)
QueueLimit2 requests
ReplenishmentPeriod5 seconds
TokensPerPeriod3 tokens added per period
AutoReplenishmenttrue
QueueProcessingOrderOldestFirst
Rejection status429

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>();

Build docs developers (and LLMs) love