Introduction

Modern APIs are frequently exposed to the internet and may receive thousands of requests every minute. While this is expected for popular applications, excessive requests from a single user, bot, or malicious actor can negatively impact performance and availability.

Rate Limiting helps protect applications by controlling how many requests a client can make within a specific time period.

Common benefits include:

In this article, you'll learn how to implement Rate Limiting in ASP.NET Core applications using the built-in Rate Limiting middleware.

What Is Rate Limiting?

Rate Limiting restricts the number of requests a client can make during a defined time window.

Example:

Limit:
100 Requests

Per:
1 Minute

If the client exceeds the limit:

HTTP 429
Too Many Requests

The request is rejected until the limit resets.

Why Use Rate Limiting?

Consider a public API.

Without rate limiting:

User
  ↓
10,000 Requests
  ↓
Server Overload

Potential issues:

With rate limiting:

User
  ↓
100 Requests/Minute
  ↓
Controlled Traffic

The application remains stable and responsive.

Built-In Rate Limiting in ASP.NET Core

Starting with .NET 7, Microsoft introduced built-in Rate Limiting middleware.

Install the package if required:

dotnet add package
Microsoft.AspNetCore.RateLimiting

Most modern ASP.NET Core templates already include the necessary support.

Configure Rate Limiting

In Program.cs, add the service.

using System.Threading.RateLimiting;

builder.Services.AddRateLimiter(
    options =>
{
    options.AddFixedWindowLimiter(
        "fixed",
        config =>
        {
            config.PermitLimit = 100;
            config.Window =
                TimeSpan.FromMinutes(1);
        });
});

This configuration allows:

100 Requests
Per Minute

for each client.

Enable the Middleware

Register the middleware.

app.UseRateLimiter();

This activates rate limiting for the application.

Apply Rate Limiting to Endpoints

Apply the policy to specific endpoints.

app.MapGet("/products", () =>
{
    return Results.Ok("Products");
})
.RequireRateLimiting("fixed");

Now the endpoint follows the configured limit.

Global Rate Limiting

You can apply a policy globally.

builder.Services.AddRateLimiter(
    options =>
{
    options.GlobalLimiter =
        PartitionedRateLimiter.Create<
            HttpContext, string>(
            context =>
            RateLimitPartition
                .GetFixedWindowLimiter(
                    "global",
                    _ => new FixedWindowRateLimiterOptions
                    {
                        PermitLimit = 100,
                        Window = TimeSpan.FromMinutes(1)
                    }));
});

All requests will use the configured limit.

Fixed Window Rate Limiting

Fixed Window is the simplest strategy.

Example:

Window:
1 Minute

Limit:
100 Requests

If 100 requests are made:

Request 101
    ↓
Rejected

The counter resets after one minute.

This approach is easy to configure and understand.

Sliding Window Rate Limiting

Sliding Window provides smoother request handling.

Instead of resetting completely:

Previous Window
+
Current Window

ASP.NET Core example:

options.AddSlidingWindowLimiter(
    "sliding",
    config =>
{
    config.PermitLimit = 100;
    config.Window =
        TimeSpan.FromMinutes(1);
});

This often produces more predictable traffic patterns.

Token Bucket Rate Limiting

Token Bucket is commonly used in APIs.

Concept:

Bucket Contains Tokens
       ↓
Request Consumes Token
       ↓
Tokens Refill Over Time

Configuration:

options.AddTokenBucketLimiter(
    "token",
    config =>
{
    config.TokenLimit = 100;
    config.TokensPerPeriod = 10;
    config.ReplenishmentPeriod =
        TimeSpan.FromSeconds(10);
});

This approach supports traffic bursts more effectively.

Custom Response for Blocked Requests

Customize the response when limits are exceeded.

builder.Services.AddRateLimiter(
    options =>
{
    options.OnRejected =
        async (context, token) =>
    {
        context.HttpContext.Response
            .StatusCode = 429;

        await context.HttpContext
            .Response
            .WriteAsync(
                "Too many requests",
                token);
    };
});

Users receive a clear message instead of a generic error.

Real-World Example

Imagine an e-commerce API.

Endpoints:

Without rate limiting:

Bot
 ↓
Thousands Of Requests
 ↓
Performance Issues

With rate limiting:

Bot
 ↓
Request Limit Reached
 ↓
Blocked

Legitimate users continue receiving fast responses.

Best Practices

When implementing rate limiting:

These practices help improve security and reliability.

Advantages of Rate Limiting

Rate Limiting offers several benefits:

These benefits are especially important for public-facing APIs.

Conclusion

Rate Limiting is an essential feature for modern ASP.NET Core applications. It helps protect APIs from abuse, controls traffic, and improves overall application reliability.

With the built-in Rate Limiting middleware introduced in .NET 7, implementing request throttling has become much simpler. Whether you choose Fixed Window, Sliding Window, or Token Bucket strategies, rate limiting provides an effective way to manage traffic and protect your services.

For production applications, combining rate limiting with authentication, monitoring, and logging creates a stronger and more resilient API architecture.