Skip to content

saurab2019/pluggable-rate-limiter-dotnet

Repository files navigation

API Rate Limiter Library (.NET)

A scalable, plug-and-play API rate limiting library built in .NET, supporting multiple algorithms like Fixed Window and Token Bucket, with both in-memory and Redis-based distributed execution.

Designed with clean architecture, extensibility, and real-world production patterns in mind.

Introduction

Modern APIs must handle unpredictable traffic, prevent abuse, and ensure fair usage across clients. This library provides a modular and extensible rate limiting solution that can be easily integrated into any .NET application using middleware.

It separates:

  • Decision-making (rate limiting)
  • Configuration (rules)
  • Execution (algorithms)

Why Rate Limiting is Needed

Without rate limiting:

  • APIs can be overwhelmed by traffic spikes
  • Malicious users can abuse endpoints
  • Backend systems can crash under load
  • No fairness between users

With rate limiting:

  • Protects system stability
  • Prevents abuse (DDoS / brute force)
  • Ensures fair usage
  • Controls traffic flow

Key Features

  • Plug-and-play middleware integration
  • Multiple algorithms:
    • Fixed Window
    • Token Bucket
  • Distributed support using Redis
  • Lua scripting for atomic operations
  • Dynamic rule updates (no restart required)
  • Clean, extensible architecture

Core Components

1. IRateLimiter (Entry Point)

Responsibility:
Main interface used by middleware to decide whether a request is allowed.

Function:

  • Receives request
  • Delegates to engine
  • Returns allow/block decision

2. RateLimiterEngine

Responsibility:
Central dispatcher that selects the correct algorithm dynamically.

Function:

  • Resolves applicable rule
  • Chooses strategy (Fixed Window / Token Bucket)
  • Executes rate limiting logic

3. IRateLimiterStrategy (Algorithm Layer)

Implementations:

  • FixedWindowRateLimiter
  • TokenBucketRateLimiter

Fixed Window

  • Limits requests within a fixed time window
  • Simple and efficient
  • Example: 5 requests per minute

Token Bucket

  • Allows burst traffic
  • Smooth refill over time
  • Example: capacity = 5, refill = 1/sec

4. RateLimitRule

Responsibility:
Defines configuration for rate limiting.

Fields:

  • RuleId
  • Algorithm type
  • Limit / Window OR Capacity / RefillRate
  • Endpoint

5. IRateLimitRuleProvider

Responsibility:
Stores and provides rules.

Current Implementation:

  • In-memory provider
  • Supports dynamic updates

6. IRateLimitRuleResolver

Responsibility:
Maps incoming request → applicable rule.

Function:

  • Matches request endpoint
  • Returns correct rule

7. IRateLimitStore

Responsibility:
Handles storage of counters/tokens.

Implementations:

InMemoryRateLimitStore

  • Fast, local
  • Used for testing

RedisRateLimitStore

  • Distributed
  • Uses Lua scripts for atomic operations

8. Key Builders

FixedWindowKeyBuilder

Builds keys like: clientId:ruleId:timeWindow

TokenBucketKeyBuilder

Builds:

  • tokens key
  • timestamp key

9. Middleware (UseRateLimiter)

Responsibility:
Intercepts every request and enforces rate limiting.

Flow:

  • Extract client info
  • Call rate limiter
  • Block or allow request

10. Admin API (Control Plane)

Responsibility:
Allows dynamic updates of rules.

Features:

  • Update Fixed Window rules
  • Update Token Bucket rules
  • No application restart required

11. Running Redis

This project supports Redis for distributed rate limiting. You can use any Redis setup (local install, cloud, or cluster).

Quick Start with Docker

docker run -d -p 6379:6379 --name redis-rate-limiter redis

Architecture Diagram

alt text

How It Works

  1. Request enters middleware
  2. Middleware builds RateLimitRequest
  3. Engine resolves rule
  4. Engine selects strategy
  5. Strategy checks store
  6. Decision returned:
    • Allowed
    • Blocked (429 Too Many Requests)

Example Configuration

builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowRule(
        ruleId: "default",
        endpoint: "/api/test",
        limit: 5,
        window: TimeSpan.FromMinutes(1)
    );

    options.AddTokenBucketRule(
        ruleId: "login",
        endpoint: "/api/login",
        capacity: 2,
        refillRate: 1 // tokens per second
    );
});

Current Capabilities

  • Multi-algorithm support
  • Distributed rate limiting
  • Dynamic configuration
  • Middleware-based enforcement

Future Enhancements

  • Sliding Window algorithm
  • Leaky Bucket algorithm
  • Per-user / API key rate limiting
  • Tier-based throttling (Free vs Premium users)
  • Metrics & analytics integration
  • Persistent rule storage (DB/config service)
  • Integration with monitoring tools (Prometheus, Grafana)
  • Circuit breaker integration

Design Principles Used

  • Strategy Pattern
  • Dependency Injection
  • Interface Segregation Principle
  • Separation of Concerns
  • Control Plane vs Data Plane

Design Trade-offs

Fixed Window

Pros:

  • Simple to implement and understand
  • Low latency and minimal computation

Cons:

  • Allows burst traffic at window boundaries (e.g., double requests at edge of time window)
  • Less accurate for smoothing traffic

Token Bucket

Pros:

  • Handles burst traffic efficiently
  • Provides smoother request distribution over time
  • Better user experience under fluctuating load

Cons:

  • Slightly more complex to implement and maintain state
  • Requires careful tuning of refill rates

Redis + Lua Scripting

Pros:

  • Ensures atomic operations in distributed environments
  • Prevents race conditions across multiple instances
  • Reduces number of network round trips

Cons:

  • Adds operational dependency on Redis
  • Increased system complexity
  • Requires handling Redis failure scenarios

Failure Handling

Redis Unavailability

  • Supports fallback strategies (e.g., in-memory rate limiting)
  • Configurable behavior:
    • Fail-Open: Allow requests when Redis is unavailable (better availability)
    • Fail-Closed: Block requests when Redis is unavailable (better protection)

Network Latency

  • Minimized Redis interactions using Lua scripts
  • Atomic operations reduce multiple round trips
  • Designed to keep request decision latency low

Race Conditions

  • Eliminated using Redis Lua scripting for atomic updates
  • Ensures consistent rate-limiting decisions across distributed instances

Scalability Considerations

  • Stateless middleware enables easy horizontal scaling across multiple application instances
  • Redis acts as a centralized coordination layer for distributed rate limiting
  • Key design ensures proper isolation (e.g., per client, per endpoint, per rule)
  • Can be extended to Redis Cluster for high throughput and fault tolerance
  • Designed to handle high concurrency with minimal contention

Support

If you find this useful, consider giving it a ⭐ on GitHub!

About

A scalable, pluggable rate limiting library in .NET supporting Fixed Window and Token Bucket algorithms with Redis-based distributed execution and dynamic rule configuration.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors