
Introduction
Public APIs are constantly exposed to abuse. Sometimes the abuse is intentional, like Denial of Service (DoS) attacks. Sometimes it is accidental, like a buggy client sending thousands of requests per second. Either way, without protection, your ASP.NET Core API can slow down, crash, or become unavailable for real users.
This is where rate limiting becomes essential.
Rate limiting controls how many requests a client can make within a specific time window. It protects your API from abuse, improves stability, and ensures fair usage across users.
In this guide, you will learn rate limiting in ASP.NET Core from fundamentals to production-ready implementation. We will cover built-in rate limiting, strategies, configuration, real-world use cases, and common mistakes—everything a senior .NET developer is expected to know.
What Is Rate Limiting?
Rate limiting is a technique that restricts the number of API requests a client can make in a given period.
Examples:
- 100 requests per minute per user
- 10 requests per second per IP
- 5 login attempts per minute
When the limit is exceeded, the server responds with:
HTTP 429 – Too Many Requests
This simple mechanism prevents:
- API abuse
- Resource exhaustion
- Performance degradation
- Unfair usage
Why Rate Limiting Is Critical for ASP.NET Core APIs
Prevents DoS and Brute-Force Attacks
Attackers often overwhelm APIs with massive traffic. Rate limiting stops excessive requests before they reach business logic.
Protects Expensive Endpoints
Endpoints like:
- File uploads
- Report generation
- Authentication
- Payment processing
should never allow unlimited requests.
Improves API Stability
Rate limiting ensures predictable load, which keeps CPU, memory, and database usage under control.
Required in Real-World Systems
Most production APIs—especially public and partner APIs—must enforce rate limits to remain reliable.
Common Rate Limiting Strategies
Before implementing rate limiting, you should understand the most common strategies.
Fixed Window Rate Limiting
Allows a fixed number of requests in a fixed time window.
Example:
- 100 requests per minute
Simple but can cause traffic spikes at window boundaries.
Sliding Window Rate Limiting
Tracks requests over a rolling time window instead of fixed intervals.
Example:
- Last 60 seconds
More accurate and fair than fixed windows.
Token Bucket Algorithm
Requests consume tokens from a bucket that refills over time.
Benefits:
- Allows short bursts
- Maintains average request rate
This is widely used in modern APIs.
Concurrency Limiting
Limits the number of concurrent requests, not total requests.
Useful for:
- Long-running operations
- File uploads
- Report generation
Rate Limiting in ASP.NET Core (Built-in Support)
ASP.NET Core provides native rate limiting middleware, which is efficient and easy to configure.
Why Use Built-in Rate Limiting?
- No third-party dependencies
- Integrated into the middleware pipeline
- Supports multiple strategies
- Highly performant
Enabling Rate Limiting in ASP.NET Core
Step 1: Add Rate Limiting Services
builder.Services.AddRateLimiter(options =>
{
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});
This sets the default response when the limit is exceeded.
Step 2: Configure a Rate Limiting Policy
Fixed Window Example
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("FixedPolicy", limiterOptions =>
{
limiterOptions.PermitLimit = 100;
limiterOptions.Window = TimeSpan.FromMinutes(1);
limiterOptions.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
limiterOptions.QueueLimit = 0;
});
});
This configuration allows:
- 100 requests per minute
- No queuing beyond the limit
Step 3: Enable Middleware
app.UseRateLimiter();
⚠️ Important:
Always place rate limiting early in the middleware pipeline, before authentication and business logic.
Applying Rate Limiting to Endpoints
Apply Rate Limiting to All Endpoints
app.MapControllers().RequireRateLimiting("FixedPolicy");
Apply Rate Limiting Per Endpoint
app.MapGet("/api/data", () => "Secure Data")
.RequireRateLimiting("FixedPolicy");
This approach gives you fine-grained control over API behavior.
IP-Based Rate Limiting
IP-based rate limiting is useful for anonymous or public APIs.
Example: Token Bucket Per IP
options.AddTokenBucketLimiter("IpPolicy", limiterOptions =>
{
limiterOptions.TokenLimit = 50;
limiterOptions.TokensPerPeriod = 10;
limiterOptions.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
limiterOptions.AutoReplenishment = true;
});
This allows:
- Short bursts
- Controlled refill rate
User-Based Rate Limiting
Authenticated APIs should rate-limit per user, not per IP.
Why User-Based Limits Matter
- Multiple users may share one IP
- Mobile networks rotate IPs
- Fair usage per account
Example Concept
Use:
- User ID
- API key
- JWT claim
as the partition key when applying rate limiting.
Rate Limiting for Authentication Endpoints
Login endpoints are prime targets for abuse.
Recommended Limits
- 5–10 attempts per minute per user
- Temporary lockout after repeated failures
Why This Matters
Rate limiting authentication:
- Prevents brute-force attacks
- Protects user accounts
- Reduces audit and security incidents
Handling Rate Limit Responses Properly
When the limit is exceeded, return meaningful headers.
Example Response
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Why Headers Matter
Clients can:
- Retry gracefully
- Avoid aggressive retries
- Improve user experience
Distributed Rate Limiting (Important for Scaling)
The Problem
In multi-instance deployments:
- Each server tracks limits independently
- Users can bypass limits by hitting different instances
The Solution
Use centralized storage, such as:
- Redis
- Distributed cache
This ensures consistent rate limiting across all instances.
Rate Limiting vs Throttling
These terms are often confused.
Rate Limiting
- Rejects requests beyond the limit
- Returns 429
- Protects the system
Throttling
- Slows down requests
- Queues or delays responses
- Maintains availability
In practice, APIs often use both together.
Common Mistakes to Avoid
Applying One Limit to All Endpoints
Different endpoints have different costs. Authentication, uploads, and reports should have stricter limits.
Rate Limiting After Heavy Middleware
Always apply rate limiting before:
- Database access
- External API calls
- File processing
Ignoring Client Feedback
Not returning Retry-After headers leads to poor client behavior and retry storms.
Forgetting About Distributed Environments
Rate limiting must work across instances, not just locally.
Interview Tip: How to Answer Rate Limiting Questions
If asked:
“How do you protect ASP.NET Core APIs from abuse?”
A strong answer:
- Explain rate limiting
- Mention built-in middleware
- Discuss strategies (fixed, sliding, token bucket)
- Talk about IP vs user-based limits
- Mention distributed rate limiting with Redis
This shows architecture-level thinking.
Real-World Use Cases
Rate limiting is commonly applied to:
- Public APIs
- Login and OTP endpoints
- File uploads
- Report generation
- Payment and checkout APIs
Any endpoint that is expensive or sensitive should be rate-limited.
Conclusion
Rate limiting is not an optional feature—it is a core API security and performance requirement.
With proper rate limiting:
- Your APIs remain stable
- Abuse is controlled
- Infrastructure costs stay predictable
- User experience improves
ASP.NET Core makes rate limiting simple, powerful, and scalable. When you apply it correctly, you move from writing APIs to engineering reliable systems.
❓ FAQ: Rate Limiting in ASP.NET Core APIs
❓ What is rate limiting in ASP.NET Core?
Rate limiting in ASP.NET Core restricts how many requests a client can send to an API within a defined time window. It helps prevent abuse, improves performance, and protects APIs from DoS attacks.
❓ What HTTP status code is returned when rate limiting is exceeded?
ASP.NET Core returns HTTP 429 – Too Many Requests when the configured rate limit is exceeded. This response may also include a Retry-After header.
❓ Does ASP.NET Core support rate limiting out of the box?
Yes. ASP.NET Core provides built-in rate limiting middleware that supports fixed window, sliding window, token bucket, and concurrency limiting strategies without third-party libraries.
❓ What is the best rate limiting strategy for APIs?
There is no single best strategy:
- Fixed window is simple
- Sliding window is more accurate
- Token bucket allows bursts
- Concurrency limiting protects long-running operations
Most production APIs use token bucket or sliding window.
❓ Should rate limiting be applied before authentication?
Yes. Rate limiting should be applied early in the middleware pipeline, usually before authentication and business logic, to stop abusive traffic as soon as possible.
❓ Is IP-based rate limiting enough?
IP-based rate limiting works for public APIs, but it is not sufficient for authenticated systems. User-based or API key–based rate limiting provides more accurate and fair control.
❓ How do I implement rate limiting in a load-balanced environment?
In multi-instance deployments, rate limiting must use centralized storage such as Redis or distributed cache. Otherwise, users can bypass limits by hitting different servers.
❓ What endpoints should always be rate limited?
Endpoints that should always have rate limiting:
- Login and authentication
- OTP and password reset
- File uploads
- Payment and checkout
- Report generation
❓ Is rate limiting the same as throttling?
No.
- Rate limiting rejects requests beyond a limit
- Throttling slows or queues requests
Many systems use both together.
Related Articles
- Handling Large File Uploads in ASP.NET Core: Best Practices, Performance, and Security
- How to Fix CORS Error in ASP.NET Core API
- ASP.NET Core Swagger Not Showing – Complete Solution Guide
- Why IQueryable Is Dangerous in APIs (Real-World Risks, Examples, and Best Practices)
- Add Serilog Without Breaking Dependency Injection in ASP.NET Core
- REST vs RESTful vs GraphQL
