Rate Limiting in .NET Core 7 Web API

What is Rate Limiting?

  • Rate limiting is the process used to restrict the number of requests allowed to a particular resource in the specified time window.
  • .NET Core 7 has an inbuilt rate limiter middleware using which we can configure settings related to rate limiting.

Why is Rate Limiting?

  • Rate limiting is for limiting network traffic.
  • Rate limiting protects our application from denial-of-service attacks (DoS).
  • It helps us to manage server resources efficiently when a high volume of requests is received.
  • Rate limiting helps us improve the performance of our application by reducing unnecessary delays to send back responses.
  • Rate Limiting reduces cost. For example, suppose our API is publicly available and the end-user made a high volume of request. In that case, it may require additional server and network resources to manage that load which increase infrastructure cost.

Rate Limiting Algorithm

Fixed Window

  • Fixed Window is a simple and memory-efficient algorithm that divides time into a fixed window or time interval corresponding to the rate-limiting definition, and if the number request limit is exceeded, then the further request is throttled.
  • For example – Suppose the fixed window algorithm allows 20 requests per minute. In that case, the one window starts at 00.00.00 to 00.01.00, and it allows 20 requests within that window, and after a time frame of the fixed window, the request count renews at the beginning of every time frame.

Sliding Window

  • The sliding window algorithm is a combination of fixed and Sliding log algorithms and is divide the window into multiple segments and counts the number of requests within each segment. The window slides each passing and discards the old request counts, and allows the new one’s current segment. 

Token Bucket

  • Token Bucket is a memory-efficient algorithm that uses a bucket to store a fixed number of tokens and maintained count.
  • For example- Suppose have a 100-token limit for a bucket, and whenever the requests will come it will check whether the token is available in the bucket or not. If a token is available, it will refill new requests and decrease the token count. Otherwise, if the token limit is exceeded and not available in that case, requests are getting throttled.

Leaky Bucket

  • The Leaky Bucket algorithm uses the bucket with a hole to store the number of tokens, and each token specifies the API request. It will be stored in FIFO (First in First out) queue with a fixed size to hold the number of requests if a new request will come that will be added at the end of the queue, and if the queue is getting full then throttled the subsequent request.

Sliding Log

  • Sliding Log algorithm tracks a timestamp log for each API request, and that will be stored internally inside the hashed database and sorted by time. This algorithm helps to control the number of requests per unit of time and data transferred by the same. When a new request is processed then the sum of log entries corresponding to that particular user is calculated to find the request rate. If that rate exceeds the limit, then subsequent requests are throttled.

Rate Limiting in .NET Core 7

ASP.NET Core has built support for Rate Limiter and has middleware for the same.

Step 1

Create a .NET Core 7 Web API Application.

Step 2

Create a new controller with different API endpoints as per requirement.

Step 3

Open the Program class and configure the fixed window rate limiter inside the same.

//Fixed Window Rate Litter Configuration
builder.Services.AddRateLimiter(_ => _
    .AddFixedWindowLimiter(policyName: "fixed", options =>
    {
        options.PermitLimit = 3;
        options.Window = TimeSpan.FromSeconds(10);
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    }));

Line 2: AddRateLimiter function to add rate limiting service inside service collection.

Line 3: AddFixedWindowLimiter to add a fixed window policy with a policy name fixed.

Line 5-6: PermitLimit 3 and Window have a 10-second timespan means 3 requests are allowed within a 10-second window timespan.

Line 7-8: QueueProcessingOrder is the OldestFirst, and QueueLimit is 2 means whenever the window limit is exceeded, in that case, subsequent two requests are throttled and stored inside the queue. When the window count is reset at that time requests are processed from the queue and the oldest request is picked for processing.

Step 4

Add UseRateLimiter middleware inside the program class to enable rate limiting in the request/response pipeline.

//Rate limitter middleware
app.UseRateLimiter();

Step 5

Inside the controller apply the rate limiter with the help of EnableRateLimiting attribute on any endpoint or controller level as per requirement.

If you want to disable the rate limiter on the particular endpoint that is possible using the DisableRateLimiting attribute.


using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using RudderStackDemo.Entities;
using RudderStackDemo.Repositories;

namespace RudderStackDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [EnableRateLimiting("fixed")]
    public class ProductsController : ControllerBase
    {
        private readonly IProductService _productService;

        public ProductsController(IProductService productService)
        {
            _productService = productService;
        }

        /// <summary>
        /// Product List
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [EnableRateLimiting("fixed")]
        public async Task<IActionResult> ProductListAsync()
        {
            var productList = await _productService.ProductListAsync();
            if (productList != null)
            {
                return Ok(productList);
            }
            else
            {
                return NoContent();
            }
        }

        /// <summary>
        /// Get Product By Id
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        [HttpGet("{productId}")]
        [DisableRateLimiting]
        public async Task<IActionResult> GetProductDetailsByIdAsync(int productId)
        {
            var productDetails = await _productService.GetProductDetailByIdAsync(productId);
            if (productDetails != null)
            {
                return Ok(productDetails);
            }
            else
            {
                return NotFound();
            }
        }
    }
}

Step 6

Execute and Test API endpoints with the help of Swagger or Postman.

Github URL

https://github.com/Jaydeep-007/RateLimitDemo

Conclusion

In this article, we discuss what is rate limiters and the different algorithms related to them. After that, step-by-step implementation using .NET Core 7 and understanding the functionality of fixed window rate limiter.

Happy Coding!