### Install RedisRateLimiting NuGet Packages Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Install the core library and the optional ASP.NET Core integration package using the NuGet Package Manager Console or the .NET CLI. ```xml PM> Install-Package RedisRateLimiting PM> Install-Package RedisRateLimiting.AspNetCore dotnet add package RedisRateLimiting dotnet add package RedisRateLimiting.AspNetCore ``` -------------------------------- ### Install RedisRateLimiting.AspNetCore NuGet Package Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md Install the RedisRateLimiting.AspNetCore NuGet package to integrate Redis-based rate limiting into your ASP.NET Core application. This package depends on RedisRateLimiting. ```xml PM> Install-Package RedisRateLimiting.AspNetCore ``` -------------------------------- ### Install RedisRateLimiting NuGet Package Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md Use the Package Manager Console to install the RedisRateLimiting NuGet package. This package provides the core rate limiting functionalities. ```xml PM> Install-Package RedisRateLimiting ``` -------------------------------- ### Complete ASP.NET Core Application Bootstrap with Redis Rate Limiting Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt This snippet shows the full Program.cs file for an ASP.NET Core application, demonstrating the setup and registration of multiple Redis-based rate limiting policies, including concurrency, fixed window, sliding window, token bucket, and a custom per-client policy. It also configures the global 429 response handler and activates the rate limiting middleware. ```csharp using Microsoft.EntityFrameworkCore; using RedisRateLimiting.AspNetCore; using StackExchange.Redis; var builder = WebApplication.CreateBuilder(args); // 1. Connect to Redis var redisOptions = ConfigurationOptions.Parse( builder.Configuration.GetConnectionString("Redis")!); var connectionMultiplexer = ConnectionMultiplexer.Connect(redisOptions); builder.Services.AddSingleton(connectionMultiplexer); // 2. Register all rate limiting policies builder.Services.AddRateLimiter(options => { options.AddRedisConcurrencyLimiter("concurrency", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 5; }); options.AddRedisConcurrencyLimiter("concurrency_queue", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 2; opt.QueueLimit = 3; }); options.AddRedisFixedWindowLimiter("fixed_window", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 10; opt.Window = TimeSpan.FromSeconds(30); }); options.AddRedisSlidingWindowLimiter("sliding_window", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 10; opt.Window = TimeSpan.FromSeconds(30); }); options.AddRedisTokenBucketLimiter("token_bucket", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.TokenLimit = 10; opt.TokensPerPeriod = 2; opt.ReplenishmentPeriod = TimeSpan.FromSeconds(5); }); // Per-tenant dynamic policy options.AddPolicy("client_id"); // Global 429 response header handler options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); builder.Services.AddControllers(); var app = builder.Build(); app.UseRateLimiter(); // ← must come before MapControllers app.MapControllers(); app.Run(); ``` -------------------------------- ### Per-Client Dynamic Concurrency Limits with RedisRateLimitPartition Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Implement custom rate limiting policies where limits are determined dynamically per client, loaded from a database. This example uses `RedisRateLimitPartition.GetConcurrencyRateLimiter` to create isolated Redis limiters for each unique client identifier. ```csharp // Methods available: // RedisRateLimitPartition.GetConcurrencyRateLimiter(partitionKey, factory) // RedisRateLimitPartition.GetFixedWindowRateLimiter(partitionKey, factory) // RedisRateLimitPartition.GetSlidingWindowRateLimiter(partitionKey, factory) // RedisRateLimitPartition.GetTokenBucketRateLimiter(partitionKey, factory) // Example: per-client dynamic concurrency limits loaded from a database public class ClientIdRateLimiterPolicy( IConnectionMultiplexer connectionMultiplexer, IServiceProvider serviceProvider, ILogger logger) : IRateLimiterPolicy { public Func? OnRejected => (context, _) => { context.HttpContext.Response.StatusCode = 429; return ValueTask.CompletedTask; }; public RateLimitPartition GetPartition(HttpContext httpContext) { // Partition key = value of custom X-ClientId header var clientId = httpContext.Request.Headers["X-ClientId"].ToString(); using var scope = serviceProvider.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); // Load per-tenant limits from DB var rateLimit = db.Clients .Where(x => x.Identifier == clientId) .Select(x => x.RateLimit) .FirstOrDefault(); var permitLimit = rateLimit?.PermitLimit ?? 1; logger.LogInformation("Client: {clientId} PermitLimit: {permitLimit}", clientId, permitLimit); // Each unique clientId gets its own isolated Redis limiter return RedisRateLimitPartition.GetConcurrencyRateLimiter(clientId, _ => new RedisConcurrencyRateLimiterOptions { PermitLimit = permitLimit, QueueLimit = rateLimit?.QueueLimit ?? 0, ConnectionMultiplexerFactory = () => connectionMultiplexer, }); } } // Register the policy by type (not by name): builder.Services.AddRateLimiter(options => { options.AddPolicy("client_id_policy"); }); // Apply to a controller: [ApiController] [Route("[controller]")] [EnableRateLimiting("client_id_policy")] public class ClientsController : ControllerBase { [HttpGet] public async Task Get() { await Task.Delay(2000); return Ok("client-scoped response"); } } ``` -------------------------------- ### Configure Redis Fixed Window Rate Limiter Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md Configure the ASP.NET Core services to use the Redis Fixed Window Rate Limiter. This example sets a permit limit of 1 and a window of 2 seconds, using a provided ConnectionMultiplexer factory. ```csharp builder.Services.AddRateLimiter(options => { options.AddRedisFixedWindowLimiter("demo_fixed_window", (opt) => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 1; opt.Window = TimeSpan.FromSeconds(2); }); }); ``` -------------------------------- ### Configure Redis Concurrency Rate Limiter Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md Configure the ASP.NET Core services to use the Redis Concurrency Rate Limiter. This example sets a permit limit of 5 and uses a provided ConnectionMultiplexer factory. Uncomment 'opt.QueueLimit' to enable request queuing. ```csharp builder.Services.AddRateLimiter(options => { options.AddRedisConcurrencyLimiter("demo_concurrency", (opt) => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 5; // Queue requests when the limit is reached //opt.QueueLimit = 5 }); }); ``` -------------------------------- ### Add Redis Token Bucket Limiter Configuration Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Registers a named token-bucket policy. The bucket starts full at TokenLimit tokens; each request consumes one token. Every ReplenishmentPeriod interval, TokensPerPeriod tokens are added back. Burst traffic is absorbed up to the bucket capacity, while steady-state throughput is governed by the replenishment rate. ```csharp builder.Services.AddRateLimiter(options => { // Bucket of 10, refill 2 tokens every 5 seconds → ~24 req/min sustained options.AddRedisTokenBucketLimiter("token_bucket_api", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.TokenLimit = 10; // max burst opt.TokensPerPeriod = 2; // tokens added each period opt.ReplenishmentPeriod = TimeSpan.FromSeconds(5); }); options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); [ApiController] [Route("[controller]")] public class TokenBucketController : ControllerBase { [HttpGet] [EnableRateLimiting("token_bucket_api")] public IActionResult Get() => Ok("token consumed"); } // Burst: first 10 back-to-back requests all succeed immediately. // After the burst: requests succeed at a rate of 2 per 5 seconds. // Empty bucket response: // HTTP/1.1 429 Too Many Requests // Retry-After: 5 ``` -------------------------------- ### Configure Redis Sliding Window Rate Limiter Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md Use this extension method to add a Redis-based sliding window rate limiter. Configure the Redis connection and rate limiting parameters like permit limit and window size. ```csharp builder.Services.AddRateLimiter(options => { options.AddRedisSlidingWindowLimiter("demo_sliding_window", (opt) => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 1; opt.Window = TimeSpan.FromSeconds(2); }); }); ``` -------------------------------- ### Configure Redis Token Bucket Rate Limiter Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/README.md This extension method configures a Redis-based token bucket rate limiter. Set the token limit, tokens replenished per period, and the replenishment period. ```csharp builder.Services.AddRateLimiter(options => { options.AddRedisTokenBucketLimiter("demo_token_bucket", (opt) => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.TokenLimit = 2; opt.TokensPerPeriod = 1; opt.ReplenishmentPeriod = TimeSpan.FromSeconds(2); }); }); ``` -------------------------------- ### Standard Rate Limit Response Headers with RateLimitMetadata.OnRejected Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Configure ASP.NET Core rate limiting to automatically include standard HTTP response headers (Limit, Remaining, Reset, Retry-After) when a request is rejected. This uses a pre-built handler that reads metadata from the `RateLimitLease`. ```csharp // Header constants (RedisRateLimiting.AspNetCore.RateLimitHeaders): // RateLimitHeaders.Limit → "X-RateLimit-Limit" // RateLimitHeaders.Remaining → "X-RateLimit-Remaining" // RateLimitHeaders.Reset → "X-RateLimit-Reset" // RateLimitHeaders.RetryAfter → "Retry-After" // Metadata keys (RedisRateLimiting.RateLimitMetadataName): // RateLimitMetadataName.Limit → MetadataName ("RATELIMIT_LIMIT") // RateLimitMetadataName.Remaining → MetadataName ("RATELIMIT_REMAINING") // RateLimitMetadataName.Reset → MetadataName ("RATELIMIT_RESET") // RateLimitMetadataName.RetryAfter → MetadataName ("RATELIMIT_RETRYAFTER") // Wire up globally in Program.cs: builder.Services.AddRateLimiter(options => { options.AddRedisFixedWindowLimiter("api_limit", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 100; opt.Window = TimeSpan.FromMinutes(1); }); // Use the pre-built handler: options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); // Or write a custom handler that augments the pre-built one: options.OnRejected = async (context, ct) => { await RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); // Log or emit metrics on every rejection var logger = context.HttpContext.RequestServices .GetRequiredService>(); logger.LogWarning("Rate limit exceeded for {path}", context.HttpContext.Request.Path); }; // Example 429 response headers produced: // HTTP/1.1 429 Too Many Requests // X-RateLimit-Limit: 100/1m // X-RateLimit-Remaining: 0 // X-RateLimit-Reset: 47 // Retry-After: 47 ``` -------------------------------- ### Add Redis Fixed Window Limiter Configuration Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Registers a named fixed-window policy. All requests within the same time window share a single Redis counter. Best suited for simple 'N requests per M seconds' quotas where burst behavior at window boundaries is acceptable. ```csharp builder.Services.AddRateLimiter(options => { // Allow 10 requests per 1-minute window options.AddRedisFixedWindowLimiter("fixed_window_api", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 10; opt.Window = TimeSpan.FromMinutes(1); }); options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); // Apply at controller class level — every action in this controller is covered [ApiController] [Route("[controller]")] [EnableRateLimiting("fixed_window_api")] public class FixedWindowController : ControllerBase { [HttpGet] public IActionResult Get() => Ok("within limit"); } // On the 11th request within the same window: // HTTP/1.1 429 Too Many Requests // X-RateLimit-Limit: 10/1m // X-RateLimit-Remaining: 0 // X-RateLimit-Reset: 38 ← seconds until window resets // Retry-After: 38 ``` -------------------------------- ### Add Redis Sliding Window Limiter Configuration Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Registers a named sliding-window policy. The allowed quota is evaluated relative to the current request's timestamp, so bursts that straddle a window boundary are still bounded. No more than PermitLimit requests can succeed within any rolling interval equal to Window. ```csharp builder.Services.AddRateLimiter(options => { // Max 20 requests in any rolling 30-second window options.AddRedisSlidingWindowLimiter("sliding_window_api", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 20; opt.Window = TimeSpan.FromSeconds(30); }); options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); [ApiController] [Route("api/[controller]")] public class WeatherController : ControllerBase { [HttpGet] [EnableRateLimiting("sliding_window_api")] public IActionResult GetForecast() => Ok("forecast data"); } // Compared to fixed window: if 20 requests arrived at 0:59 and 20 more at 1:01 // Fixed window: all 40 succeed (20 in each window bucket) // Sliding window: only the first 20 succeed; the next 20 are rejected until // the oldest recorded request falls outside the 30-second window. ``` -------------------------------- ### Configure Redis Concurrency Limiter in ASP.NET Core Source: https://context7.com/cristipufu/aspnetcore-redis-rate-limiting/llms.txt Register a named concurrency policy to limit the number of simultaneously in-flight requests. Configure options like PermitLimit, QueueLimit, and ExpectedRequestTimeout. The OnRejected event handler can be used to propagate standard rate-limit headers. ```csharp // Program.cs — full bootstrap example using StackExchange.Redis; using RedisRateLimiting.AspNetCore; var builder = WebApplication.CreateBuilder(args); var connectionMultiplexer = ConnectionMultiplexer.Connect("localhost:6379"); builder.Services.AddSingleton(connectionMultiplexer); builder.Services.AddRateLimiter(options => { // Simple concurrency limit: max 5 parallel requests options.AddRedisConcurrencyLimiter("concurrency_strict", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 5; // opt.QueueLimit = 5; // allow up to 5 queued requests // opt.TryDequeuePeriod = TimeSpan.FromMilliseconds(500); // dequeue check interval // opt.ExpectedRequestTimeout = TimeSpan.FromSeconds(60); // auto-reclaim after 60 s }); // With queuing: 2 active + 3 queued options.AddRedisConcurrencyLimiter("concurrency_queue", opt => { opt.ConnectionMultiplexerFactory = () => connectionMultiplexer; opt.PermitLimit = 2; opt.QueueLimit = 3; }); // Propagate standard rate-limit headers on 429 responses options.OnRejected = (context, ct) => RateLimitMetadata.OnRejected(context.HttpContext, context.Lease, ct); }); var app = builder.Build(); app.UseRateLimiter(); app.MapControllers(); app.Run(); // Controller usage [ApiController] [Route("[controller]")] public class ConcurrencyController : ControllerBase { [HttpGet] [EnableRateLimiting("concurrency_strict")] // ← named policy applied here public async Task Get() { await Task.Delay(1000); // simulate work return Ok("ok"); } [HttpGet("queue")] [EnableRateLimiting("concurrency_queue")] public async Task GetQueued() { await Task.Delay(1000); return Ok("queued ok"); } } // When PermitLimit is exceeded: // HTTP/1.1 429 Too Many Requests // X-RateLimit-Limit: 5 // X-RateLimit-Remaining: 0 // Retry-After: 60 ``` -------------------------------- ### Configure Rate Limit Rejection Headers in C# Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/wiki/Rate-Limiting-Headers This code snippet configures the rejection handler for rate limiting. It sets the HTTP status code to 429 (Too Many Requests) and populates the response headers with rate limit details such as limit, remaining requests, reset time, and retry-after information. ```C# public static Func OnRejected { get; } = (httpContext, lease, token) => { httpContext.Response.StatusCode = 429; if (lease.TryGetMetadata(RateLimitMetadataName.Limit, out var limit)) { httpContext.Response.Headers[RateLimitHeaders.Limit] = limit; } if (lease.TryGetMetadata(RateLimitMetadataName.Remaining, out var remaining)) { httpContext.Response.Headers[RateLimitHeaders.Remaining] = remaining.ToString(); } if (lease.TryGetMetadata(RateLimitMetadataName.Reset, out var reset)) { httpContext.Response.Headers[RateLimitHeaders.Reset] = reset.ToString(); } if (lease.TryGetMetadata(RateLimitMetadataName.RetryAfter, out var retryAfter)) { httpContext.Response.Headers[RateLimitHeaders.RetryAfter] = retryAfter.ToString(); } return ValueTask.CompletedTask; }; ``` -------------------------------- ### Custom Client ID Rate Limiter Policy Source: https://github.com/cristipufu/aspnetcore-redis-rate-limiting/wiki/Custom-Rate-Limiting-Policies Implement a custom rate limiter policy that retrieves rate limit configurations from a database based on a client ID provided in the request headers. This policy uses Redis for distributed rate limiting. ```C# public class ClientIdRateLimiterPolicy : IRateLimiterPolicy { ... public ClientIdRateLimiterPolicy( IConnectionMultiplexer connectionMultiplexer, IServiceProvider serviceProvider) {} ... public RateLimitPartition GetPartition(HttpContext httpContext) { var clientId = httpContext.Request.Headers["X-ClientId"].ToString(); using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); var rateLimit = dbContext.Clients.Where(x => x.Identifier == clientId).Select(x => x.RateLimit).FirstOrDefault(); return RedisRateLimitPartition.GetRedisConcurrencyRateLimiter(clientId, key => new RedisConcurrencyRateLimiterOptions { PermitLimit = rateLimit.PermitLimit, QueueLimit = rateLimit.QueueLimit, ConnectionMultiplexerFactory = () => _connectionMultiplexer, }); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.