ASP.NET Core  

How to Implement Rate Limiting in ASP.NET Core?

Introduction

Rate limiting in ASP.NET Core is an essential technique for protecting Web APIs from abuse, preventing denial-of-service attacks, controlling traffic spikes, and ensuring fair usage of backend resources. In modern cloud-native and microservices-based architectures, implementing rate limiting helps maintain application stability, improve performance, and reduce infrastructure costs. ASP.NET Core provides built-in rate limiting middleware that makes it easier to control how many requests a client can send within a specific time window.

This guide explains in simple language how to implement rate limiting in ASP.NET Core, including configuration, policy types, and best practices for production environments.

What Is Rate Limiting?

Rate limiting is a mechanism that restricts the number of HTTP requests a client can make to an API within a defined time period.

For example:

  • A user can make 100 requests per minute

  • A specific IP address can make 10 requests per second

  • Anonymous users can access an endpoint only 5 times per minute

If the limit is exceeded, the API returns a response such as HTTP 429 (Too Many Requests).

Rate limiting improves API security, protects databases from overload, and ensures consistent performance for all users.

Why Use Rate Limiting in ASP.NET Core Web APIs?

Implementing rate limiting in ASP.NET Core applications provides several benefits:

  • Protects against brute-force attacks

  • Prevents API abuse and scraping

  • Controls server resource usage

  • Improves scalability in cloud deployments

  • Ensures fair usage among multiple clients

In enterprise ASP.NET Core Web API applications, rate limiting is considered a best practice for API security and traffic management.

Step 1: Add Rate Limiting Middleware

ASP.NET Core includes built-in rate limiting support starting from modern versions of the framework.

In Program.cs, register rate limiting services:

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

This configuration allows 100 requests per minute per client.

Step 2: Enable Rate Limiting Middleware

After registering services, enable the middleware:

app.UseRateLimiter();

Make sure this middleware is added before endpoint mapping in the pipeline.

Step 3: Apply Rate Limiting to Endpoints

You can apply rate limiting globally or to specific controllers or endpoints.

Example for an endpoint:

[EnableRateLimiting("fixed")]
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok("Rate limited data");
    }
}

This ensures the defined rate limiting policy is applied only to this controller.

Types of Rate Limiting Strategies

ASP.NET Core supports different rate limiting algorithms.

Fixed Window Rate Limiting

Allows a fixed number of requests per time window.

Example:

  • 100 requests per minute

Simple and easy to implement, but traffic spikes can occur at window boundaries.

Sliding Window Rate Limiting

Distributes requests more evenly over time.

This reduces sudden spikes and provides smoother traffic control.

Token Bucket Rate Limiting

Uses tokens that refill over time. Each request consumes a token.

If tokens are exhausted, further requests are rejected.

This approach is flexible and commonly used in high-performance API systems.

Concurrency Limiting

Limits the number of concurrent requests instead of total requests per time period.

Useful for protecting database connections and CPU-intensive operations.

Customizing Rate Limiting by IP or User

You can create policies based on:

  • Client IP address

  • Authenticated user ID

  • API key

Example using partitioned rate limiting:

options.AddPolicy("ip-policy", context =>
    RateLimitPartition.GetFixedWindowLimiter(
        partitionKey: context.Connection.RemoteIpAddress?.ToString(),
        factory: _ => new FixedWindowRateLimiterOptions
        {
            PermitLimit = 50,
            Window = TimeSpan.FromMinutes(1)
        }));

This ensures each IP address has its own request limit.

Returning Custom Error Responses

When rate limits are exceeded, the API returns HTTP 429.

You can customize the response:

options.OnRejected = async (context, token) =>
{
    context.HttpContext.Response.StatusCode = 429;
    await context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
};

Custom error messages improve API usability and client experience.

Best Practices for Production Rate Limiting

  • Use different limits for anonymous and authenticated users

  • Combine rate limiting with authentication and logging

  • Monitor request metrics using observability tools

  • Use distributed rate limiting for multi-instance deployments

  • Configure limits based on real traffic patterns

In cloud-native ASP.NET Core deployments, distributed caching solutions such as Redis can help synchronize rate limits across multiple instances.

Common Mistakes When Implementing Rate Limiting

  • Applying very strict limits that block legitimate users

  • Forgetting to enable middleware

  • Not handling HTTP 429 responses properly

  • Ignoring scaling scenarios in load-balanced environments

Careful configuration ensures balanced API performance and security.

Summary

Implementing rate limiting in ASP.NET Core involves registering rate limiting services, configuring policies such as fixed window, sliding window, token bucket, or concurrency limits, and applying them to specific endpoints or globally. Rate limiting protects REST APIs from abuse, improves scalability, and ensures fair usage in enterprise and cloud-native applications. By combining proper configuration, monitoring, and distributed support for multi-instance deployments, developers can build secure, reliable, and high-performance ASP.NET Core Web APIs that handle traffic efficiently and safely.