I'm always excited to take on new projects and collaborate with innovative minds.

Social Links

Web Development

Implementing Rate Limiting on Web APIs using ASP.NET Core and Redis

Implementing Rate Limiting on Web APIs using ASP.NET Core and Redis

If you’ve ever built a public-facing API, you’ve likely run into the issue of clients making too many requests—sometimes intentionally, sometimes by accident. Left unchecked, this can overwhelm your backend, slow down your service, or even take your API offline.

A simple, scalable, and efficient way to handle this is Rate Limiting.

In this post, I’ll walk you through implementing rate limiting in an ASP.NET Core Web API using Redis as the distributed cache store. This approach is production-ready, efficient under load, and works well even when you’re running your API on multiple servers.


Why Rate Limiting?

Some common real-world reasons for implementing rate limiting:

  • Prevent abuse or malicious traffic
  • Ensure fair usage across multiple clients
  • Protect backend databases and services from overload
  • Control API consumption for free vs paid plans

High-Level Approach

Here’s what we’ll do:

  • Build a simple ASP.NET Core Web API
  • Use Redis to store and check request counters per client
  • Allow X number of requests per client per time window (e.g., 100 requests per 1 minute)
  • Return 429 Too Many Requests when the limit is exceeded

Prerequisites

  • .NET 8 SDK
  • Redis server running locally or in the cloud (Docker Redis works too)
  • Any Redis client library for .NET (We’ll use StackExchange.Redis)

Project Setup

Folder Structure

RateLimitingApi/
├── Controllers/
│   └── SampleController.cs
├── Middleware/
│   └── RateLimitingMiddleware.cs
├── Services/
│   └── RateLimitingService.cs
├── Program.cs
├── appsettings.json
├── RateLimitingApi.csproj

Step 1: Install Required NuGet Packages

dotnet add package StackExchange.Redis

Step 2: Configure Redis Connection

In your Program.cs:

builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{
    var configuration = builder.Configuration.GetConnectionString("Redis");
    return ConnectionMultiplexer.Connect(configuration);
});

In your appsettings.json:

{
  "ConnectionStrings": {
    "Redis": "localhost:6379"
  }
}

(Adjust the Redis connection string as per your setup.)


Step 3: Create Rate Limiting Service

// Services/RateLimitingService.cs
using StackExchange.Redis;

public class RateLimitingService
{
    private readonly IDatabase _redisDb;
    private readonly int _limit = 100;
    private readonly TimeSpan _timeWindow = TimeSpan.FromMinutes(1);

    public RateLimitingService(IConnectionMultiplexer redis)
    {
        _redisDb = redis.GetDatabase();
    }

    public async Task<bool> IsLimitExceededAsync(string clientId)
    {
        var key = $"rate_limit:{clientId}";
        var count = await _redisDb.StringIncrementAsync(key);

        if (count == 1)
        {
            await _redisDb.KeyExpireAsync(key, _timeWindow);
        }

        return count > _limit;
    }
}

Step 4: Create Rate Limiting Middleware

// Middleware/RateLimitingMiddleware.cs
public class RateLimitingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly RateLimitingService _rateLimiter;

    public RateLimitingMiddleware(RequestDelegate next, RateLimitingService rateLimiter)
    {
        _next = next;
        _rateLimiter = rateLimiter;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var clientId = context.Connection.RemoteIpAddress?.ToString() ?? "unknown";

        if (await _rateLimiter.IsLimitExceededAsync(clientId))
        {
            context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
            await context.Response.WriteAsync("Rate limit exceeded. Try again later.");
            return;
        }

        await _next(context);
    }
}

Step 5: Register Everything in Program.cs

using RateLimitingApi.Middleware;
using RateLimitingApi.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<RateLimitingService>();
builder.Services.AddControllers();

var app = builder.Build();

app.UseMiddleware<RateLimitingMiddleware>();
app.MapControllers();

app.Run();

Step 6: Create a Sample API Endpoint

// Controllers/SampleController.cs
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("[controller]")]
public class SampleController : ControllerBase
{
    [HttpGet("hello")]
    public IActionResult Get()
    {
        return Ok("Hello, World!");
    }
}

Testing the Rate Limiting

You can now start your API:

dotnet run

Then hit the endpoint repeatedly:

GET http://localhost:5000/sample/hello

After exceeding 100 requests within a minute (from the same IP), you’ll start getting:

HTTP 429 Too Many Requests
Rate limit exceeded. Try again later.

Benefits of Using Redis for Rate Limiting

  • Distributed support: Works across multiple app servers
  • Fast in-memory reads and writes: Keeps latency low
  • Built-in key expiry support: Automatically resets counters after the time window

GitHub Repository

I’ve pushed the complete working code here:

👉 GitHub Repo: https://github.com/DheerGupta35959/RateLimitingApi


Final Thoughts

Rate limiting is one of those things that many teams leave till late, but it’s critical for the long-term health and stability of your APIs. This approach using ASP.NET Core and Redis is simple, scalable, and works well even in cloud environments like Azure or AWS.

ASP.NET Core API Rate Limiting, Redis Rate Limiting .NET, ASP.NET Core Redis Middleware, API Protection ASP.NET Core, Distributed Rate Limiting with Redis, ASP.NET Core Performance Tips, Prevent API Abuse ASP.NET Core, API Throttling Middleware .NET, Rate Limiting Example .NET 8
4 min read
Jun 28, 2025
By Dheer Gupta
Share

Leave a comment

Your email address will not be published. Required fields are marked *

Related posts

Jul 20, 2025 • 4 min read
Building a Role-Based Access System in Node.js Without a Framework

Learn how to build a role-based access control (RBAC) system in pure N...

Jun 27, 2025 • 4 min read
Building Custom ASP.NET Core Middleware for Request-Response Logging with Elasticsearch (Centralized API Monitoring)