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:

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:

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:

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:

Advantages:

Limitations:

Traffic spikes can occur at window boundaries.

Sliding Window

Instead of resetting all requests at once, the time window moves continuously.

Benefits include:

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:

  1. A request reaches the API.

  2. The rate limiter evaluates the configured policy.

  3. If the request is within the allowed limit, processing continues.

  4. Authentication and authorization are performed.

  5. Business logic executes.

  6. A response is returned.

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

StrategyBest ForBurst HandlingComplexity
Fixed WindowGeneral APIsLowLow
Sliding WindowPublic APIsMediumMedium
Token BucketVariable workloadsHighMedium

Selecting the right algorithm depends on expected traffic patterns rather than choosing the most sophisticated option.

Best Practices

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:

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:

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:

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.