How to Implement Rate Limiting in .NET Core API


In modern web applications, APIs are constantly exposed to high traffic, bots, and malicious requests. Without protection, excessive requests can overload your server and degrade application performance.

This is where Rate Limiting becomes essential.

Rate limiting controls how many requests a client can make within a specified time window. It protects APIs from abuse, improves reliability, and ensures fair usage among users.

What is Rate Limiting?

Rate limiting restricts the number of API requests a client can make during a fixed time period.

Example:

100 requests per minute

If the client exceeds the limit, the API returns:

HTTP 429 - Too Many Requests

Why Use Rate Limiting?

Rate limiting provides several benefits:

  • Prevents API abuse
  • Protects against DDoS attacks
  • Reduces server load
  • Improves API stability
  • Ensures fair resource usage
  • Controls traffic spikes

Types of Rate Limiting

1. Fixed Window

Limits requests within a fixed time interval.

Example:

100 requests per minute

Simple and commonly used.

2. Sliding Window

Tracks requests dynamically over time for smoother limiting.

3. Token Bucket

Clients consume tokens for requests. Tokens refill over time.

Useful for burst traffic handling.

4. Concurrency Limiting

Limits how many requests can run simultaneously.

Prerequisites

Before starting, ensure you have:

  • .NET 7 or later installed
  • ASP.NET Core Web API project
  • Basic knowledge of middleware

Create a .NET Core Web API

Run the following command:

dotnet new webapi -n RateLimitDemo

Navigate to the project:

cd RateLimitDemo

Built-in Rate Limiting in ASP.NET Core

Starting from .NET 7, ASP.NET Core provides built-in rate limiting middleware.

Namespace used:

using System.Threading.RateLimiting;

Step 1: Configure Rate Limiting

Open Program.cs.

Add the following code:

using System.Threading.RateLimiting;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("fixed", config =>
    {
        config.PermitLimit = 5;
        config.Window = TimeSpan.FromSeconds(10);
        config.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        config.QueueLimit = 2;
    });
});

var app = builder.Build();

app.UseRateLimiter();

app.MapControllers();

app.Run();

Understanding the Configuration

PermitLimit

config.PermitLimit = 5;

Allows only 5 requests.

Window

config.Window = TimeSpan.FromSeconds(10);

Within a 10-second window.

QueueLimit

config.QueueLimit = 2;

Extra requests wait in queue.

QueueProcessingOrder

QueueProcessingOrder.OldestFirst

Processes oldest queued requests first.

Step 2: Apply Rate Limiting to Controller

Create a controller:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;

namespace RateLimitDemo.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    [EnableRateLimiting("fixed")]
    public class TestController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return Ok("Request Successful");
        }
    }
}

Step 3: Run the API

Start the application:

dotnet run

Test endpoint:

GET /api/test

After 5 requests within 10 seconds, you’ll receive:

429 Too Many Requests

Global Rate Limiting

Instead of applying per controller, you can apply globally.

Update middleware:

app.UseRateLimiter();

And map endpoints with policy.

Sliding Window Example

You can also use sliding window rate limiting.

Example:

builder.Services.AddRateLimiter(options =>
{
    options.AddSlidingWindowLimiter("sliding", config =>
    {
        config.PermitLimit = 10;
        config.Window = TimeSpan.FromMinutes(1);
        config.SegmentsPerWindow = 6;
    });
});

This provides smoother request tracking.

Token Bucket Example

Useful for burst traffic.

builder.Services.AddRateLimiter(options =>
{
    options.AddTokenBucketLimiter("token", config =>
    {
        config.TokenLimit = 10;
        config.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        config.QueueLimit = 5;
        config.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
        config.TokensPerPeriod = 5;
        config.AutoReplenishment = true;
    });
});

Custom Response for Rate Limit Exceeded

You can customize the response when the limit is exceeded.

builder.Services.AddRateLimiter(options =>
{
    options.OnRejected = async (context, token) =>
    {
        context.HttpContext.Response.StatusCode = 429;

        await context.HttpContext.Response.WriteAsync(
            "Too many requests. Please try again later.",
            token);
    };
});

Best Practices

Use Different Policies

Different endpoints may need different limits.

Example:

  • Login API → Strict limits
  • Public APIs → Moderate limits
  • Internal APIs → Relaxed limits

Combine with Authentication

Rate limit based on:

  • IP Address
  • User ID
  • API Key

Monitor API Usage

Track:

  • Rejected requests
  • Traffic spikes
  • Abuse patterns

Use tools like:

  • Prometheus
  • Grafana
  • Application Insights

Common Challenges

Distributed Systems

In multiple server environments, in-memory rate limiting may fail.

Solution:

  • Redis-based distributed caching
  • API Gateway rate limiting

Choosing Correct Limits

  • Too strict → blocks real users
    Too loose → ineffective protection

Rate Limiting with API Gateway

Many organizations implement rate limiting at the API Gateway level using:

  • Kong
  • NGINX
  • YARP
  • Azure API Management
  • This centralizes traffic management across all APIs.

Conclusion

Rate limiting is a critical feature for securing and stabilizing APIs. ASP.NET Core makes implementation simple with built-in middleware introduced in .NET 7.

By applying proper rate limiting strategies, you can:

  • Protect backend systems
  • Prevent abuse
  • Improve performance
  • Ensure fair API usage

Whether you’re building small APIs or enterprise-scale microservices, implementing rate limiting should always be part of your API security strategy.

Final Thoughts

Modern APIs must be resilient, secure, and scalable. Rate limiting is one of the easiest yet most powerful ways to achieve that.

With ASP.NET Core’s built-in support, developers can implement production-ready rate limiting with minimal code while maintaining flexibility and performance.

0 Comments Report