Previous Caching in .NET Core Swagger-OpenAPI-Documentation Next

🚦 Rate Limiting in .NET Core

📌 What is Rate Limiting?

Rate limiting is a technique used to control the number of requests a client can make to an API within a specified time window. It helps protect resources, prevent abuse, and ensure fair usage across clients. It is an essential strategy for building resilient, secure, and scalable ASP.NET Core applications by preventing resource overuse, ensuring fair usage, and protecting against attacks.

Since ASP.NET Core 7, built-in middleware has been available in the Microsoft.AspNetCore.RateLimiting namespace, offering a standardized and straightforward way to apply rate limiting.

Common Rate Limiting Algorithms

The ASP.NET Core rate limiting middleware supports several popular algorithms, each with its own characteristics.

1. Fixed Window

How it works: Divides time into fixed, non-overlapping intervals (windows). It allows a set number of requests within each window.

Behavior: When a new window begins, the request limit is reset. This can cause "burstiness" at the start of a new window if multiple clients try to access the resource at once.

Best for: Simple, straightforward use cases where burst traffic at window boundaries is acceptable.

2. Sliding Window

How it works: Similar to the fixed window but more advanced. It divides the time window into segments and tracks the request count for each segment.

Behavior: The window then "slides" forward, providing smoother request distribution and preventing burstiness.

Best for: General-purpose APIs that need reliable traffic shaping.

3. Token Bucket

How it works: Uses a "bucket" that holds tokens, where each token represents a request. Tokens are added at a constant rate.

Behavior: Each request consumes a token. If the bucket is empty, the request is rejected or queued. Handles bursts by using accumulated tokens.

Best for: APIs needing flexibility to handle traffic bursts while maintaining a consistent average rate.

4. Concurrency

How it works: Limits the number of concurrent requests instead of using time windows.

Behavior: Reduces available permits when a request starts and releases them when it finishes.

Best for: Protecting limited resources like database connection pools.

🛠️ How to Implement Rate Limiting in .NET Core

Step 1: Register Rate Limiting Services

Add the rate limiter service in Program.cs and configure a policy.

builder.Services.AddRateLimiter(options =>
{
    options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
    options.AddFixedWindowLimiter(policyName: "fixed", options =>
    {
        options.PermitLimit = 5;
        options.Window = TimeSpan.FromSeconds(10);
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    });
});

Step 2: Apply Policy to an Endpoint

[EnableRateLimiting("fixed")]
[HttpGet]
public IEnumerable<string> GetProducts()
{
    return new string[] { "Product A", "Product B", "Product C" };
}

[DisableRateLimiting]
[HttpGet("no-limit")]
public string GetNoLimit()
{
    return "This endpoint has no rate limit.";
}

Step 3: Test the Rate Limit

Accessing /api/products will be subject to the fixed-window limit. Extra requests will be queued or return 429 Too Many Requests.

Partitioned Rate Limiting

For user or IP-based limits, use a partitioned rate limiter with a partition key during configuration.

✅ When to Use Rate Limiting

  • Public APIs exposed to external clients
  • Preventing denial-of-service (DoS) attacks
  • Ensuring fair usage across tenants or users
  • Protecting expensive operations (e.g., database queries)

🚫 When Not to Use Rate Limiting

  • Internal APIs with trusted clients
  • Real-time systems where latency is critical
  • Operations that must always succeed (e.g., health checks)

🌟 Advantages

  • Improves API reliability and availability
  • Protects against abuse and brute-force attacks
  • Helps manage infrastructure load

⚠️ Disadvantages

  • Can block legitimate users if thresholds are too strict
  • Requires careful configuration and monitoring
  • May add complexity to client-side error handling

🧯 Precautions

  • Use meaningful error messages (e.g., HTTP 429 Too Many Requests)
  • Log rate-limited requests for analysis
  • Test limits under load to avoid false positives
  • Consider user identity or IP address for partitioning

🧠 Best Practices

  • Use different policies for different endpoints
  • Combine rate limiting with authentication and quotas
  • Use distributed rate limiting (e.g., Redis) for multi-server setups
  • Provide retry-after headers to guide clients
Back to Index
Previous Caching in .NET Core Swagger-OpenAPI-Documentation Next
*