Rate Limiting Algorithms in Web API’s in .NET

Chaitanya (Chey) Penmetsa
CodeNx
Published in
4 min readApr 1, 2024

In this blog we will see how what are different Rate Limiting algorithms and implement them using Microsoft.AspNetCore.RateLimiting NuGet package in .NET Web API. For understanding basic more on Rate Limiting basics please read below blog.

Below are the different Rate Limit Algorithms available in Microsoft.AspNetCore.RateLimiting middleware:

  • Fixed Window
  • Sliding Window
  • Token Bucket
  • Concurrency

Let us go through each of them with code examples.

Fixed Window Algorithm

This algorithm counts the number of requests made within a fixed time window. At the start of each time window, the request counter resets to zero. Each incoming request increments the counter.

Pros

  • Simple to implement.
  • Easy to understand.

Cons

  • Vulnerable to bursts of requests at the start of each time window

Below is example on how we configure the Fixed Window Algorithm and use that at endpoint level.

// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddFixedWindowLimiter("Fixed", opt => {
opt.Window = TimeSpan.FromSeconds(10);
opt.PermitLimit = 4;
opt.QueueLimit = 2;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});

options.RejectionStatusCode = 429;
});

app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithFixedRateAlgorithm")]
[EnableRateLimiting("Fixed")]
public IEnumerable<WeatherForecast> GetWithFixedRateAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

Sliding Window Algorithm

This algorithm tracks the timestamps of recent requests within a sliding time window. Maintains a log of timestamps for each request, then removes timestamps outside the sliding window. The sliding window limiter operates much like the fixed window limiter but introduces segments within each window. Every segment moves forward one by one at the segment interval. This segment interval is calculated as the window time divided by the number of segments per window.

Pros

  • Allows for smoother rate limiting over time.

Cons

  • Requires more memory to store timestamps.

Below is the illustration of how sliding window will progress and how total request limit will change as time progresses. Please note below the incoming requests are at the start of the Segment, this assumption was made to make below explanation easier.

Image created by author

Below is example on how we configure above Sliding Window Algorithm and use that at endpoint level.

// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddSlidingWindowLimiter("Sliding", opt => {
opt.PermitLimit = 100;
opt.Window = TimeSpan.FromMinutes(30);
opt.SegmentsPerWindow = 3;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
});

options.RejectionStatusCode = 429;
});

app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithSlidingAlgorithm")]
[EnableRateLimiting("Sliding")]
public IEnumerable<WeatherForecast> GetWithSlidingAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

Token Bucket Algorithm

Allows a burst of requests up to a limit and refills at a fixed rate. Requests consume tokens from a bucket, whereas bucket is refilled at a constant rate. The token bucket limiter is like the sliding window limiter, but rather than adding back the requests taken from the expired segment, a fixed number of tokens are added each replenishment period. The tokens added each segment can’t increase the available tokens to a number higher than the token bucket limit.

Pros

  • Allows bursts of requests while maintaining an overall limit.

Cons

  • Requires tracking timestamps for token refills.

The following table shows a token bucket limiter with a limit of 100 tokens and a 10-second replenishment period.

Image Taken from Microsoft site

Below is example on how we configure above Token Bucket Algorithm and use that at endpoint level.

// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddTokenBucketLimiter("Token", opt => {
opt.TokenLimit = 100;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
opt.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
opt.TokensPerPeriod = 10; //Rate at which you want to fill
opt.AutoReplenishment = true;
});

options.RejectionStatusCode = 429;
});

app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithTokenAlgorithm")]
[EnableRateLimiting("Token")]
public IEnumerable<WeatherForecast> GetWithTokenAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

Concurrency Algorithm

Concurrency limiting is the simplest form of rate limiting, focusing on the number of simultaneous requests being processed. The concurrency limiter limits the number concurrent requests. Each request reduces the concurrency limit by one. When a request completes, the limit is increased by one. Unlike the other requests limiters that limit the total number of requests for a specified period, the concurrency limiter limits only the number of concurrent requests and doesn’t cap the number of requests in an interval.

Below is example on how we configure above Concurrency Algorithm and use that at endpoint level.

// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddConcurrencyLimiter("Concurrency", opt => {
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
opt.PermitLimit = 100;
});

options.RejectionStatusCode = 429;
});

app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithConcurrency")]
[EnableRateLimiting("Concurrency")]
public IEnumerable<WeatherForecast> GetWithConcurrencyAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

With this we conclude this blog on different rate limiting algorithms and their implementation in .NET Web API. In future blog let’s look at how we can implement these policies with Minimal API’s.

Source code can be found in below link:

🙏Thanks for taking the time to read the article. If you found it helpful and would like to show support, please consider:

  1. 👏👏👏👏👏👏Clap for the story and bookmark for future reference
  2. Follow me on Chaitanya (Chey) Penmetsa for more content
  3. Stay connected on LinkedIn.

Wishing you a happy learning journey 📈, and I look forward to sharing new articles with you soon.

--

--

Chaitanya (Chey) Penmetsa
CodeNx
Editor for

👨🏽‍💻Experienced and passionate software enterprise architect helping solve real-life business problems with innovative, futuristic, and economical solutions.