Skip to content

codingdroplets/dotnet-rate-limiting-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Rate Limiting in ASP.NET Core Web API (.NET 10)

All four built-in rate limiting algorithms in one place β€” Fixed Window, Sliding Window, Token Bucket, and Concurrency Limiter with real endpoints, integration tests, and HTTP 429 responses done right.

.NET ASP.NET Core License: MIT Visit CodingDroplets YouTube Patreon Buy Me a Coffee GitHub


πŸš€ Support the Channel β€” Join on Patreon

If this sample saved you time, consider joining our Patreon community. You'll get exclusive .NET tutorials, premium code samples, and early access to new content β€” all for the price of a coffee.

πŸ‘‰ Join CodingDroplets on Patreon

Prefer a one-time tip? Buy us a coffee β˜•


🎯 What You'll Learn

  • How to configure all four built-in rate limiting algorithms in ASP.NET Core
  • How to apply policies per-controller or per-action with [EnableRateLimiting]
  • How to exempt specific endpoints using [DisableRateLimiting]
  • How to return structured HTTP 429 Too Many Requests responses with Retry-After headers
  • How to use the modern Scalar UI (OpenAPI) for interactive API exploration
  • How to write integration tests that exercise rate-limited endpoints

πŸ—ΊοΈ Architecture Overview

Incoming HTTP Request
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          ASP.NET Core Middleware Pipeline             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚         app.UseRateLimiter()  ← FIRST          β”‚  β”‚
β”‚  β”‚  Checks policy for this endpoint               β”‚  β”‚
β”‚  β”‚                                                β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚  Within limit?                          β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  YES β†’ forward to controller            β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  NO  β†’ OnRejected β†’ HTTP 429            β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                      β”‚
β”‚  Controllers annotated with [EnableRateLimiting("x")]β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                          β”‚
        β–Ό                          β–Ό
  200 OK Response        429 Too Many Requests
                         + Retry-After header
                         + Problem Details JSON

πŸ“‹ Rate Limiting Algorithms at a Glance

Algorithm Policy Name Config Best For
Fixed Window fixed 5 req / 10 s Simple API throttling
Sliding Window sliding 10 req / 20 s (4 segments) Smooth burst control
Token Bucket token 8 tokens, refill 2 / 5 s Burst + steady average
Concurrency concurrency Max 3 concurrent Protecting slow resources

πŸ“ Project Structure

dotnet-rate-limiting-api/
β”œβ”€β”€ dotnet-rate-limiting-api.sln
β”œβ”€β”€ RateLimitingApi/
β”‚   β”œβ”€β”€ Controllers/
β”‚   β”‚   β”œβ”€β”€ FixedWindowController.cs      ← Fixed Window demo
β”‚   β”‚   β”œβ”€β”€ SlidingWindowController.cs    ← Sliding Window demo
β”‚   β”‚   β”œβ”€β”€ TokenBucketController.cs      ← Token Bucket demo
β”‚   β”‚   β”œβ”€β”€ ConcurrencyController.cs      ← Concurrency Limiter demo
β”‚   β”‚   └── NoLimitController.cs          ← [DisableRateLimiting] demo
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   β”œβ”€β”€ ApiResponse.cs                ← Generic response envelope
β”‚   β”‚   └── Product.cs                    ← Sample domain model
β”‚   β”œβ”€β”€ Properties/
β”‚   β”‚   └── launchSettings.json
β”‚   └── Program.cs                        ← All rate limiters registered here
└── RateLimitingApi.Tests/
    └── RateLimitingIntegrationTests.cs   ← 16 integration tests

πŸ› οΈ Prerequisites

  • .NET 10 SDK
  • Any IDE: Visual Studio 2022+, VS Code, or JetBrains Rider

⚑ Quick Start

# Clone the repo
git clone https://github.com/codingdroplets/dotnet-rate-limiting-api.git
cd dotnet-rate-limiting-api

# Build
dotnet build -c Release

# Run the API
cd RateLimitingApi
dotnet run

# Open Scalar UI β†’ http://localhost:5289/scalar/v1

πŸ”§ How It Works

Step 1 β€” Register All Policies in Program.cs

builder.Services.AddRateLimiter(options =>
{
    // 1. Fixed Window β€” 5 requests per 10 seconds
    options.AddFixedWindowLimiter(policyName: "fixed", opt =>
    {
        opt.PermitLimit = 5;
        opt.Window      = TimeSpan.FromSeconds(10);
        opt.QueueLimit  = 2;
    });

    // 2. Sliding Window β€” 10 requests per 20 seconds (4 segments)
    options.AddSlidingWindowLimiter(policyName: "sliding", opt =>
    {
        opt.PermitLimit       = 10;
        opt.Window            = TimeSpan.FromSeconds(20);
        opt.SegmentsPerWindow = 4;
        opt.QueueLimit        = 2;
    });

    // 3. Token Bucket β€” 8 tokens, replenish 2 every 5 seconds
    options.AddTokenBucketLimiter(policyName: "token", opt =>
    {
        opt.TokenLimit          = 8;
        opt.ReplenishmentPeriod = TimeSpan.FromSeconds(5);
        opt.TokensPerPeriod     = 2;
        opt.AutoReplenishment   = true;
        opt.QueueLimit          = 2;
    });

    // 4. Concurrency β€” max 3 simultaneous requests
    options.AddConcurrencyLimiter(policyName: "concurrency", opt =>
    {
        opt.PermitLimit = 3;
        opt.QueueLimit  = 2;
    });

    // Custom 429 response with Retry-After header
    options.OnRejected = async (context, ct) =>
    {
        context.HttpContext.Response.StatusCode = 429;
        context.HttpContext.Response.Headers["Retry-After"] = "10";
        await context.HttpContext.Response.WriteAsJsonAsync(new
        {
            status = 429,
            error  = "Too Many Requests",
            message = "Rate limit exceeded. Please wait before retrying.",
            retryAfterSeconds = 10
        }, cancellationToken: ct);
    };
});

// IMPORTANT: UseRateLimiter() must come before MapControllers()
app.UseRateLimiter();

Step 2 β€” Apply Policies to Controllers

// Apply a named policy to all actions in this controller
[EnableRateLimiting("fixed")]
public class FixedWindowController : ControllerBase { ... }

// Exempt an endpoint from all rate limiting
[DisableRateLimiting]
public class NoLimitController : ControllerBase { ... }

πŸ“‘ API Endpoints

No Rate Limit

Method Endpoint Description
GET /api/nolimit/status API status & policy overview

Fixed Window (5 req / 10 s)

Method Endpoint Description
GET /api/fixedwindow/products List all products
GET /api/fixedwindow/products/{id} Get product by ID

Sliding Window (10 req / 20 s)

Method Endpoint Description
GET /api/slidingwindow/orders List all orders
GET /api/slidingwindow/orders/{id} Get order by ID

Token Bucket (8 tokens, +2 per 5 s)

Method Endpoint Description
GET /api/tokenbucket/reports List all reports
GET /api/tokenbucket/reports/{id} Get report by ID

Concurrency Limiter (max 3 concurrent)

Method Endpoint Description
GET /api/concurrency/inventory List inventory (simulated slow query)
GET /api/concurrency/inventory/{id} Get inventory item by ID

πŸ§ͺ Running Tests

dotnet test -c Release

16 integration tests cover all five controllers:

Area Coverage
Happy path 200 OK for all controllers
Not found 404 for all controllers
JSON content-type Validated on all responses
Response envelope success: true structure verified

πŸ€” When to Use Each Algorithm

Use Case Best Algorithm
Simple API key / per-IP throttle Fixed Window
Smooth traffic shaping, no boundary spikes Sliding Window
Allow short bursts, enforce an average rate Token Bucket
Protect expensive DB queries / third-party APIs Concurrency

🌐 Interactive API Explorer

Once running, open Scalar UI in your browser:

http://localhost:5289/scalar/v1

OpenAPI JSON spec:

http://localhost:5289/openapi/v1.json

πŸ“š References


πŸ“„ License

This project is licensed under the MIT License.


πŸ”— Connect with CodingDroplets

Platform Link
🌐 Website https://codingdroplets.com/
πŸ“Ί YouTube https://www.youtube.com/@CodingDroplets
🎁 Patreon https://www.patreon.com/CodingDroplets
β˜• Buy Me a Coffee https://buymeacoffee.com/codingdroplets
πŸ’» GitHub http://github.com/codingdroplets/

Want more samples like this? Support us on Patreon or buy us a coffee β˜• β€” every bit helps keep the content coming!

About

Learn all four built-in rate limiting algorithms in ASP.NET Core Web API (.NET 10): Fixed Window, Sliding Window, Token Bucket, and Concurrency Limiter with Scalar UI.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages