patterncsharpdotnetModerate
Rate limiting middleware: configuring fixed window and per-user policies
Viewed 0 times
.NET 7+
rate limiting aspnetAddRateLimiterFixedWindowLimiterRequireRateLimiting429 too many requests
Problem
APIs without rate limiting are vulnerable to abuse and denial-of-service attacks. Implementing rate limiting manually in every handler is inconsistent and bypassed easily.
Solution
Use the built-in ASP.NET Core rate limiting middleware (.NET 7+):
builder.Services.AddRateLimiter(options =>
{
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
// Global fixed window policy
options.AddFixedWindowLimiter("global", opt =>
{
opt.Window = TimeSpan.FromMinutes(1);
opt.PermitLimit = 100;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
});
// Per-user policy using partition key
options.AddPolicy("perUser", ctx =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: ctx.User.Identity?.Name ?? ctx.Connection.RemoteIpAddress?.ToString() ?? "anon",
factory: _ => new FixedWindowRateLimiterOptions
{
Window = TimeSpan.FromMinutes(1),
PermitLimit = 30
}));
});
app.UseRateLimiter();
// Apply to endpoint
app.MapPost("/api/orders", handler).RequireRateLimiting("perUser");Why
The rate limiter uses System.Threading.RateLimiting primitives which are partition-aware and support queuing. Requests exceeding limits are either rejected immediately or queued depending on QueueLimit.
Gotchas
- UseRateLimiter() must appear after UseRouting() so endpoint metadata is available for policy selection
- Rate limit state is in-memory and per-instance — use distributed Redis partitions for multi-instance deployments
- Rate limiting on load balancers (nginx, AWS ALB) is often more efficient than application-level limiting
Revisions (0)
No revisions yet.