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.
Multiple Policies
Large applications often require multiple rate limiting policies.
Example:
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("Login", limiter =>
{
limiter.PermitLimit = 5;
limiter.Window = TimeSpan.FromMinutes(5);
});
options.AddFixedWindowLimiter("PublicApi", limiter =>
{
limiter.PermitLimit = 500;
limiter.Window = TimeSpan.FromMinutes(1);
});
});
Why Use Multiple Policies?
Authentication endpoints require much stricter protection than read-only APIs.
Separating policies prevents attackers from abusing sensitive endpoints while allowing legitimate traffic to continue flowing through less expensive operations.
Fixed Window vs Sliding Window vs Token Bucket
| Strategy | Best For | Burst Handling | Complexity |
|---|---|---|---|
| Fixed Window | General APIs | Low | Low |
| Sliding Window | Public APIs | Medium | Medium |
| Token Bucket | Variable workloads | High | Medium |
Selecting the right algorithm depends on expected traffic patterns rather than choosing the most sophisticated option.
Best Practices
Apply different limits for different endpoints.
Protect authentication endpoints aggressively.
Return meaningful HTTP 429 responses.
Monitor rejected request counts.
Log excessive traffic patterns.
Use asynchronous request processing.
Test limits under realistic production workloads.
Review rate limits periodically as application usage changes.
Common Mistakes
One common mistake is applying the same limit to every endpoint. High-cost operations such as report generation or file uploads often require much stricter limits than read-only APIs.
Another issue is configuring limits that are too restrictive. Legitimate users may experience unnecessary failures during periods of increased activity.
Developers also sometimes assume authentication alone prevents abuse. Even authenticated users can unintentionally or intentionally generate excessive traffic.
Testing and Validation
Before deploying rate limiting, validate the implementation thoroughly.
Recommended testing includes:
Burst traffic simulation
Sustained load testing
HTTP 429 response verification
Endpoint-specific policy testing
Concurrent client testing
Authentication endpoint testing
Performance benchmarking
Monitoring rejected request metrics
Testing should confirm that legitimate users remain unaffected while abusive traffic is appropriately limited.
Performance Considerations
Rate limiting introduces minimal overhead compared to executing business logic or database queries.
To maximize efficiency:
Reject excessive requests as early as possible.
Avoid unnecessary queuing.
Monitor request rejection rates.
Keep policy definitions simple.
Profile application performance under peak load.
Combine rate limiting with response caching where appropriate.
Properly configured rate limiting often improves overall application performance by preventing resource exhaustion.
Security Considerations
Rate limiting is an important security control but should not be used in isolation.
Combine it with:
Authentication
Authorization
Input validation
HTTPS
Web Application Firewalls (WAF)
DDoS protection
Audit logging
Threat monitoring
Layered security provides stronger protection against both accidental overload and malicious attacks.
Troubleshooting
Clients Receive HTTP 429 Too Frequently
Review configured limits and compare them with actual traffic patterns. The policy may be too restrictive for normal usage.
Rate Limiting Appears Not to Work
Verify that UseRateLimiter() is added to the middleware pipeline and that endpoints reference the intended policy.
Login Requests Are Still Being Abused
Ensure that authentication endpoints have stricter policies than general API endpoints and consider combining rate limiting with account lockout mechanisms.
Uneven User Experience
Evaluate whether a sliding window or token bucket strategy better matches the application's traffic characteristics.
Conclusion
Rate limiting is an essential part of building resilient ASP.NET Core 10 applications. By controlling request volume before expensive processing occurs, developers can improve application stability, reduce infrastructure costs, and protect APIs from abuse. Whether you're securing authentication endpoints, public APIs, or resource-intensive operations, choosing the appropriate rate limiting strategy and applying endpoint-specific policies helps create applications that remain responsive under both normal and peak traffic conditions.

Jasen FiciPosted Aug 6, 2026, 12:54 PM
We featured this for DotNetNews readers here: https://dotnetnews.co/archive/the-net-news-daily-issue-513/'