Every public-facing API eventually encounters traffic spikes. Some requests come from legitimate users, while others originate from automated bots, aggressive crawlers, or malicious actors attempting denial-of-service (DoS) attacks or abusing expensive endpoints. Without proper safeguards, a small number of clients can consume a disproportionate amount of server resources, degrading performance for everyone else.
Rate limiting is one of the simplest and most effective ways to protect an ASP.NET Core application. Introduced as built-in middleware in recent .NET releases and further refined in ASP.NET Core 10, it allows developers to enforce request quotas without relying on third-party libraries for common scenarios.
In this article, you'll learn how to implement production-ready rate limiting, choose the right limiting strategy, apply different policies to different endpoints, and avoid common implementation mistakes.
What Is Rate Limiting?
Understanding Rate Limiting
Rate limiting controls how many requests a client can make within a specified period.
For example:
100 requests per minute
10 login attempts every five minutes
1,000 API requests per hour
5 file uploads every minute
When a client exceeds the configured limit, the server rejects additional requests until the limit resets.
Rate limiting protects server resources while ensuring fair access for all clients.
Why Rate Limiting Matters
Without rate limiting, an application may experience:
API abuse
Credential stuffing attacks
Excessive database traffic
Increased infrastructure costs
Poor user experience during traffic spikes
Resource exhaustion
Rate limiting complements authentication, authorization, and input validation by preventing excessive request volume before expensive processing begins.
Enabling Rate Limiting
Register the rate limiting services during application startup.
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("ApiPolicy", limiter =>
{
limiter.PermitLimit = 100;
limiter.Window = TimeSpan.FromMinutes(1);
limiter.QueueLimit = 0;
});
});
Enable the middleware.
var app = builder.Build();
app.UseRateLimiter();
Why This Configuration?
This configuration creates a fixed-window policy that allows up to 100 requests every minute.
Once the limit is reached, additional requests are rejected immediately because the queue limit is zero. Rejecting excess requests prevents requests from accumulating and consuming server resources unnecessarily.
Applying Policies to Endpoints
Rate limiting can be applied selectively.
app.MapGet("/products", GetProducts)
.RequireRateLimiting("ApiPolicy");
Why Apply Policies Per Endpoint?
Different endpoints have different resource requirements.
For example:
Product catalog: high request limit
Login endpoint: very low limit
Report generation: strict limit
File upload: limited concurrency
Applying policies individually allows each endpoint to enforce limits appropriate to its workload.
Fixed Window vs Sliding Window
ASP.NET Core supports multiple rate limiting algorithms.
Fixed Window
Requests are counted within fixed intervals.
Example:
100 requests between 10:00 and 10:01
Counter resets at 10:01
Advantages:
Simple
Predictable
Easy to configure
Limitations:
Traffic spikes can occur at window boundaries.
Sliding Window
Instead of resetting all requests at once, the time window moves continuously.
Benefits include:
Smoother traffic distribution
Fairer request handling
Reduced burst traffic
Sliding windows are often preferable for APIs with unpredictable request patterns.
Token Bucket Limiting
Token bucket limiting allows occasional bursts while maintaining an average request rate.
Imagine a bucket containing tokens.
Each request consumes one token.
Tokens are replenished at a steady rate.
If no tokens remain, additional requests are rejected until more tokens become available.
This approach works well for APIs where occasional bursts are acceptable but sustained abuse should be prevented.
End-to-End Implementation
Consider an online ordering platform.
Architecture:
Customer
│
▼
ASP.NET Core API
│
┌───┴───────────────┐
▼ ▼
Rate Limiter Authentication
│
Business Services
│
SQL Database
Workflow:
A request reaches the API.
The rate limiter evaluates the configured policy.
If the request is within the allowed limit, processing continues.
Authentication and authorization are performed.
Business logic executes.
A response is returned.
Requests exceeding the configured quota receive an HTTP 429 (Too Many Requests) response.
By rejecting excessive requests before expensive operations begin, the application protects downstream services and improves overall stability.

Join the conversation! Your thoughts help the community grow.