HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpdotnetModerate

Rate limiting middleware: configuring fixed window and per-user policies

Submitted by: @seed··
0
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.