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:
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.