A reusable rate limiting library for .NET microservices
$ dotnet add package DriveM.RateLimit.CoreA reusable rate limiting library for .NET 8 microservices. This library provides flexible and configurable rate limiting functionality that can be easily integrated into any ASP.NET Core application.
dotnet add package DriveM.RateLimit.Core
Program.cs file:// Add rate limiting services
builder.Services.AddRateLimiting(options =>
{
// Optional: Configure global rate limiting
options.EnableGlobalRateLimiting = true;
options.DefaultMaxRequests = 100; // 100 requests
options.DefaultTimeWindowInSeconds = 60; // per minute
// Optional: Configure client identification method for global rate limiting
options.GlobalClientResolverStrategy = ClientResolverStrategy.IpAddress;
});
// Add rate limiting middleware - place before endpoints/controllers
app.UseRateLimiting();
app.MapControllers();
[HttpGet]
[RateLimit(MaxRequests = 5, TimeWindowInSeconds = 60)] // 5 requests per minute
public IActionResult Get()
{
return Ok("Rate limited endpoint");
}
You can configure global rate limit settings and then selectively override them at the endpoint level. Values that are not explicitly specified in the attribute will be inherited from global settings:
// In Program.cs - set global defaults
builder.Services.AddRateLimiting(options =>
{
options.EnableGlobalRateLimiting = true;
options.DefaultMaxRequests = 100; // 100 requests global default
options.DefaultTimeWindowInSeconds = 60; // 60 second window global default
});
// Endpoint with fully custom settings (ignores global defaults)
[RateLimit(MaxRequests = 5, TimeWindowInSeconds = 30)]
public IActionResult FullyCustom() { ... }
// Endpoint that inherits time window from global, but customizes max requests
[RateLimit(MaxRequests = 5)]
public IActionResult CustomRequestsOnly() { ... } // Uses 5 requests per 60 seconds
// Endpoint that only customizes the client resolver but uses global limits
[RateLimit(ClientResolverStrategy = ClientResolverStrategy.UserId)]
public IActionResult CustomStrategyOnly() { ... } // Uses 100 requests per 60 seconds
// Endpoints without attributes still get global rate limiting (if enabled)
public IActionResult NoAttribute() { ... } // Falls back to global limits
This flexibility allows you to establish baseline limits for your API while fine-tuning specific endpoints as needed.
The library supports several strategies for identifying clients:
// IP Address only (default)
[RateLimit(MaxRequests = 10, TimeWindowInSeconds = 60, ClientResolverStrategy = ClientResolverStrategy.IpAddress)]
// IP Address + Request Path
[RateLimit(MaxRequests = 5, TimeWindowInSeconds = 30, ClientResolverStrategy = ClientResolverStrategy.IpAndPath)]
// User ID (from claims)
[RateLimit(MaxRequests = 20, TimeWindowInSeconds = 60, ClientResolverStrategy = ClientResolverStrategy.UserId)]
// Custom header
[RateLimit(MaxRequests = 100, TimeWindowInSeconds = 60, ClientResolverStrategy = ClientResolverStrategy.CustomHeader)]When using CustomHeader, you can specify the header name in options:
services.AddRateLimiting(options =>
{
options.ClientIdentifierHeader = "X-API-Key";
});services.AddRateLimiting(options =>
{
options.IncludeRateLimitHeaders = true;
options.RateLimitHeader = "X-RateLimit-Limit";
options.RateLimitRemainingHeader = "X-RateLimit-Remaining";
});For scaling across multiple instances, use a distributed cache implementation:
// Add your preferred distributed cache implementation
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
// Register rate limiting services
builder.Services.AddRateLimiting();For detailed instructions on how to create and publish the NuGet package for this library, please refer to the NUGET.md documentation.
MIT