# How To Use Rate Limiting In ASP.NET Core

> Rate limiting is a technique to limit the number of requests to a server or an API. ASP.NET Core 7 has a built-in rate limiter middleware that's easy to integrate into your API. We're going to cover four rate limiting algorithms: fixed window, sliding window, token bucket, and concurrency.

Published: 2023-04-08. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/how-to-use-rate-limiting-in-aspnet-core

ASP.NET Core 7 introduced built-in rate limiting middleware in the `Microsoft.AspNetCore.RateLimiting` namespace.
You register policies with `AddRateLimiter`, apply the middleware with `app.UseRateLimiter`, and attach a policy using the `EnableRateLimiting` attribute on controllers or `RequireRateLimiting` on Minimal API endpoints.

Rate limiting is a technique to limit the number of requests to a server or an API.

A limit is introduced within a given time period to prevent server overload and protect against abuse.

In ASP.NET Core 7, we have a built-in rate limiter middleware that's easy to integrate into your API.

We're going to cover four rate limiter algorithms:

- [Fixed window](#fixed-window-limiter)
- [Sliding window](#sliding-window-limiter)
- [Token bucket](#token-bucket-limiter)
- [Concurrency](#concurrency-limiter)

Let's see how we can work with rate limiting.

## What Is Rate Limiting?

Rate limiting is about restricting the number of requests to an API, usually within a specific time window or based on other criteria.

This is practical for a few reasons:

- Prevents overloading of servers or applications
- Improves security and guards against DDoS attacks
- Reduces costs by preventing unnecessary resource usage

In a multi-tenant application, each unique user can have a limitation on the number of API requests.

## Configuring Rate Limiting

ASP.NET Core 7 introduced built-in rate limiting middleware in the `Microsoft.AspNetCore.RateLimiting` namespace.

To add rate limiting to your application, you first need to register the rate limiting services:

```csharp
builder.Services.AddRateLimiter(options =>
{
    options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;

    // We'll talk about adding specific rate limiting policies later.
});
```

I suggest updating the `RejectionStatusCode` to `429 (Too Many Requests)` because it's more correct.
The default value is `503 (Service Unavailable)`.

And you also have to apply the `RateLimitingMiddleware`:

```csharp
app.UseRateLimiter();
```

That's everything you'll need.

Let's see the rate limiting algorithms we can use.

## Fixed Window Limiter

The `AddFixedWindowLimiter` method configures a fixed window limiter.

The `Window` value determines the time window.

When a time window expires, a new one starts, and the request limit is reset.

```csharp
builder.Services.AddRateLimiter(rateLimiterOptions =>
{
    rateLimiterOptions.AddFixedWindowLimiter("fixed", options =>
    {
        options.PermitLimit = 10;
        options.Window = TimeSpan.FromSeconds(10);
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 5;
    });
});
```

## Sliding Window Limiter

The sliding window algorithm is similar to the fixed window, but it introduces segments in a window.

Here's how it works:

- Each time window is divided into multiple segments
- The window slides one segment each segment interval
- The segment interval is (window_time)/(segments_per_window)
- When a segment expires, the requests taken in that segment are added to the current segment

The `AddSlidingWindowLimiter` method configures a sliding window limiter.

```csharp
builder.Services.AddRateLimiter(rateLimiterOptions =>
{
    rateLimiterOptions.AddSlidingWindowLimiter("sliding", options =>
    {
        options.PermitLimit = 10;
        options.Window = TimeSpan.FromSeconds(10);
        options.SegmentsPerWindow = 2;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 5;
    });
});
```

## Token Bucket Limiter

The token bucket algorithm is similar to the sliding window, but instead of adding back the requests from the expired segment,
a fixed number of tokens are added after each replenishment period.

The total number of tokens can never exceed the token limit.

The `AddTokenBucketLimiter` method configures a token bucket limiter.

```csharp
builder.Services.AddRateLimiter(rateLimiterOptions =>
{
    rateLimiterOptions.AddTokenBucketLimiter("token", options =>
    {
        options.TokenLimit = 100;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 5;
        options.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
        options.TokensPerPeriod = 20;
        options.AutoReplenishment = true;
    });
});
```

When `AutoReplenishment` is `true`, an internal timer will execute every `ReplenishmentPeriod` and replenish the tokens.

## Concurrency Limiter

The concurrency limiter is the most straightforward algorithm, and it just limits the number of concurrent requests.

The `AddConcurrencyLimiter` method configures a concurrency limiter.

```csharp
builder.Services.AddRateLimiter(rateLimiterOptions =>
{
    rateLimiterOptions.AddConcurrencyLimiter("concurrency", options =>
    {
        options.PermitLimit = 10;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 5;
    });
});
```

There's no time component involved in this case. The only parameter is the number of concurrent requests.

## Using Rate Limiting In Your API

Now that we have configured our rate limiting policies, let's see how we can use them in our API.

There are slight differences between controllers and minimal API endpoints, so I'll cover them in separate examples.

**Controllers**

To add rate limiting on a controller we use the `EnableRateLimiting` and `DisableRateLimiting` attributes.

`EnableRateLimiting` can be applied on the controller or on the individual endpoints.

```csharp
[EnableRateLimiting("fixed")]
public class TransactionsController
{
    private readonly ISender _sender;

    public TransactionsController(ISender sender)
    {
        _sender = sender;
    }

    [EnableRateLimiting("sliding")]
    public async Task<IActionResult> GetTransactions()
    {
        return Ok(await _sender.Send(new GetTransactionsQuery()));
    }

    [DisableRateLimiting]
    public async Task<IActionResult> GetTransactionById(int id)
    {
        return Ok(await _sender.Send(new GetTransactionByIdQuery(id)));
    }
}
```

In the previous example:

- All endpoints in the `TransactionsController` will use a **fixed window** policy
- The `GetTransactions` endpoint will use a **sliding window** policy
- The `GetTransactionById` endpoint won't have any rate limiting applied

**Minimal APIs**

In a [**Minimal API**](https://milanjovanovic.tech/blog/minimal-apis-dotnet) endpoint you can configure the rate limit policy by calling `RequireRateLimiting` and specifying the policy name.

We're using the **token bucket** policy in this example.

```csharp
app.MapGet("/transactions", async (ISender sender) =>
{
    return Results.Ok(await sender.Send(new GetTransactionsQuery()));
})
.RequireRateLimiting("token");
```

## Closing Thoughts

It's great that we can quickly introduce **rate limiting** in ASP.NET Core.

You can choose from one of the existing rate limiter algorithms:

- Fixed window
- Sliding window
- Token bucket
- Concurrency

Here are some resources if you want to learn more about rate limiting:

- [Rate Limiting pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/rate-limiting-pattern)
- [Announcing Rate Limiting for .NET](https://devblogs.microsoft.com/dotnet/announcing-rate-limiting-for-dotnet/)

I'm excited to try out rate limiting in my projects.

That's all for today.

Have an awesome Saturday!

---

## Frequently asked questions

### What is rate limiting?

Rate limiting is a technique that restricts the number of requests to a server or API, usually within a specific time window. It prevents server overload, improves security by guarding against DDoS attacks, and reduces costs from unnecessary resource usage.

### How do you add rate limiting in ASP.NET Core?

ASP.NET Core 7 introduced built-in rate limiting middleware in the Microsoft.AspNetCore.RateLimiting namespace. You register policies with AddRateLimiter, apply the middleware with app.UseRateLimiter, then attach policies using the EnableRateLimiting attribute on controllers or RequireRateLimiting on Minimal API endpoints.

### What is the difference between fixed window and sliding window rate limiting?

A fixed window limiter resets the request limit every time the window expires. A sliding window limiter divides the window into segments and slides forward one segment at a time, adding the requests from the expired segment back to the current one.

### How does the token bucket rate limiting algorithm work?

A token bucket limiter adds a fixed number of tokens after each replenishment period, and the total can never exceed the token limit. With auto replenishment enabled, an internal timer refills the tokens every replenishment period.

### What is a concurrency limiter?

A concurrency limiter is the most straightforward rate limiting algorithm. It simply caps the number of concurrent requests, with no time component involved. The only parameter is how many requests may run at the same time.

### What status code should a rate-limited API return?

429 Too Many Requests is the more correct choice. The ASP.NET Core rate limiter's default rejection status code was 503 Service Unavailable, so it's worth setting RejectionStatusCode to 429 explicitly.
