Wednesday, September 3, 2025

Throttling in Web API – A Complete Guide

APIs are the backbone of modern applications, but if not protected, they can be overwhelmed by excessive requests from clients. To ensure **fair usage, reliability, and performance**, we use **Throttling** in Web API.

๐Ÿ”น What is Throttling?

Throttling is a mechanism that **limits the number of API requests a client can make within a given time frame**. It prevents abuse, protects server resources, and ensures all clients get a fair share of the system’s capacity.

For example:

* A client is allowed only **100 requests per minute**.

* If they exceed the limit, the API returns **HTTP 429 (Too Many Requests)**.

 ๐Ÿ”น Why Do We Need Throttling?

* ✅ **Prevents server overload** – Protects from heavy traffic or denial-of-service (DoS) attacks.

* ✅ **Fair usage policy** – Ensures no single user hogs all the resources.

* ✅ **Cost efficiency** – Reduces unnecessary server and bandwidth usage.

* ✅ **Improved reliability** – Keeps the API stable and consistent.

 ๐Ÿ”น Throttling Strategies

There are multiple approaches to implement throttling:

1. **Fixed Window**

   * Restricts requests in fixed time slots.

   * Example: 100 requests allowed between 12:00–12:01.

2. **Sliding Window**

   * Uses a rolling time frame for more accuracy.

   * Example: If a request is made at 12:00:30, the limit resets at 12:01:30.

3. **Token Bucket**

   * A bucket holds tokens, each request consumes one. Tokens refill at a fixed rate.

   * Allows short bursts of traffic until the bucket is empty.

4. **Leaky Bucket**

   * Similar to Token Bucket but processes requests at a fixed outflow rate.

   * Ensures smooth traffic flow without sudden spikes.

 ๐Ÿ”น Implementing Throttling in .NET Web API

 ✅ Option 1: Custom Middleware

You can create your own middleware to limit requests per client:

`csharp

public class ThrottlingMiddleware

{

    private static Dictionary<string, (DateTime timestamp, int count)> _requests = new();

    private readonly RequestDelegate _next;

    private const int LIMIT = 5; // max 5 requests

    private static readonly TimeSpan TIME_WINDOW = TimeSpan.FromMinutes(1);

    public ThrottlingMiddleware(RequestDelegate next) => _next = next;

    public async Task Invoke(HttpContext context)

    {

        var clientIp = context.Connection.RemoteIpAddress?.ToString();


        if (_requests.ContainsKey(clientIp))

        {

            var (timestamp, count) = _requests[clientIp];

            if ((DateTime.Now - timestamp) < TIME_WINDOW)

            {

                if (count >= LIMIT)

                {

                    context.Response.StatusCode = StatusCodes.Status429TooManyRequests;

                    await context.Response.WriteAsync("Too many requests. Try again later.");

                    return;

                }

                _requests[clientIp] = (timestamp, count + 1);

            }

            else

            {

                _requests[clientIp] = (DateTime.Now, 1);

            }

        }

        else

        {

            _requests[clientIp] = (DateTime.Now, 1);

        }


        await _next(context);

    }

}

Register in **Program.cs**:

csharp

app.UseMiddleware<ThrottlingMiddleware>();

 ✅ Option 2: Built-in Rate Limiting in .NET 7+

ASP.NET Core 7 introduced built-in **Rate Limiting Middleware**:


```csharp

builder.Services.AddRateLimiter(options =>

{

    options.AddFixedWindowLimiter("Fixed", opt =>

    {

        opt.Window = TimeSpan.FromSeconds(10);

        opt.PermitLimit = 5;  // 5 requests per 10 seconds

        opt.QueueLimit = 2;

        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;

    });

});


app.UseRateLimiter();

Apply to a specific endpoint:

```csharp

app.MapGet("/data", () => "Hello")

   .RequireRateLimiting("Fixed");

๐Ÿ”น Best Practices for API Throttling

* Always return **HTTP 429 Too Many Requests** when limits are hit.

* Provide a **Retry-After header** to guide clients on when to retry.

* Implement **per-user or per-IP throttling** for fairness.

* Use **distributed caching (Redis, SQL, etc.)** when running multiple servers.

* Log throttling events to monitor abuse patterns.

๐Ÿ”น Final Thoughts

Throttling is essential for any production-ready API. It helps maintain **performance, security, and fair usage**. Whether you use a **custom middleware** or the **built-in .NET rate limiter**, implementing throttling ensures your API remains **reliable and scalable**.


API Versioning in ASP.NET Core Web API – A Complete Guide

 When building Web APIs, one inevitable challenge is **change**. As your application grows, you’ll add new features, change contracts, or even remove old functionality. But what happens to existing clients who still depend on the old API?

That’s where **API versioning** comes in. It allows you to evolve your API safely without breaking existing consumers.

 ๐Ÿ”‘ Why Do We Need API Versioning?

* **Backward compatibility** – Old clients continue to work.

* **Gradual migration** – Clients can upgrade at their own pace.

* **Flexibility** – You can experiment with new versions.

* **Safe deprecation** – Retire old versions without sudden breaks.

 ๐Ÿ“Œ API Versioning Strategies

 1. **URI Path Versioning (Most Common)**

https://api.example.com/v1/customers

https://api.example.com/v2/customers

✅ Easy to use and document

❌ URL changes for every version

 2. **Query String Versioning**

https://api.example.com/customers?api-version=1.0

✅ Very simple to implement

❌ Not as RESTful (query strings are usually for filters)

3. **Header Versioning**

GET /customers

Header: api-version: 1.0

✅ Keeps URLs clean

❌ Requires client to manage headers

 4. **Content Negotiation (Media Type)**

Accept: application/json; version=1.0

✅ Standards-friendly

❌ More complex to manage

 ⚙️ Implementing Versioning in ASP.NET Core


Microsoft provides a handy NuGet package for API versioning:

powershell

Install-Package Microsoft.AspNetCore.Mvc.Versioning

 Step 1: Configure Services

csharp

public void ConfigureServices(IServiceCollection services)

{

    services.AddControllers();

    services.AddApiVersioning(options =>

    {

        options.DefaultApiVersion = new ApiVersion(1, 0); 

        options.AssumeDefaultVersionWhenUnspecified = true;

        options.ReportApiVersions = true; // Adds headers like api-supported-versions

        options.ApiVersionReader = new UrlSegmentApiVersionReader(); 

        // Options: QueryStringApiVersionReader("api-version") 

        //          HeaderApiVersionReader("x-api-version")

    });

}

Step 2: Create Versioned Controllers

`csharp

[ApiVersion("1.0")]

[Route("api/v{version:apiVersion}/customers")]

[ApiController]

public class CustomersV1Controller : ControllerBase

{

    [HttpGet]

    public IActionResult Get() => Ok("Customer list from V1");

}


[ApiVersion("2.0")]

[Route("api/v{version:apiVersion}/customers")]

[ApiController]

public class CustomersV2Controller : ControllerBase

{

    [HttpGet]

    public IActionResult Get() => Ok("Customer list from V2 with new fields");

}

 Step 3: Testing Requests

* `GET /api/v1/customers` → handled by **V1 controller**

* `GET /api/v2/customers` → handled by **V2 controller**

## ๐Ÿ”ง Best Practices for API Versioning

1. Use **URI path versioning** for public APIs (clear & user-friendly).

2. Use **Header or Media Type versioning** for internal APIs (cleaner approach).

3. Always **document versions** using Swagger (OpenAPI).

4. Define a **deprecation strategy** – mark old versions and set timelines for removal.

 ✅ Conclusion

API versioning is essential for **scalable, maintainable, and client-friendly** Web APIs. In ASP.NET Core, you can easily implement versioning using the official `Microsoft.AspNetCore.Mvc.Versioning` package.

By planning your versioning strategy early, you ensure smooth upgrades for clients and keep your API future-proof.


Don't Copy

Protected by Copyscape Online Plagiarism Checker

Pages