Skip to content

About

RateLimiter

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Distributed Rate Limiter - Complete Implementation

Overview

A production-ready, highly scalable and configurable distributed rate limiter for ASP.NET Core built with .NET 10. Implements multiple rate-limiting algorithms using the Strategy pattern, supports Redis for distributed deployments, and includes comprehensive monitoring with Prometheus metrics.

Features

✅ Multiple Algorithms

  • Token Bucket (in-memory & distributed via Redis)
  • Fixed Window Counter
  • Sliding Window Log
  • Leaky Bucket

✅ Distributed Support

  • Redis-backed repository with connection pooling
  • Atomic operations via Lua scripts
  • Distributed token bucket algorithm
  • Multi-server deployment ready

✅ Configurable Rules

  • Limit by User ID, IP Address, Client ID
  • Custom property-based limiting
  • Priority-based rule matching
  • Dynamic rule reloading (no restart required)

✅ Monitoring & Observability

  • Prometheus metrics integration
  • Serilog structured logging
  • Detailed logging for all decisions
  • Metrics export endpoint

✅ Admin API

  • CRUD operations for rate limit rules
  • Dynamic rule management
  • Metrics endpoint
  • No downtime rule updates

✅ Quality Assurance

  • Comprehensive unit tests (xUnit)
  • Integration tests with WebApplicationFactory
  • SOLID principles & design patterns
  • Repository pattern for data access

Architecture

				Client
				   │
				   ▼
		   ASP.NET Middleware
				   │
				   ▼
	   Rate Limiter Service
				   │
	   ┌───────────┼───────────┐
	   ▼           ▼           ▼
 Token Bucket  Sliding Window Fixed Window
 LeakyBucket
	   │           │           │
	   └───────────┼───────────┘
				   ▼
	┌──────────────┴──────────────┐
	▼                             ▼
 In-Memory              Redis Repository
 Repository            (Distributed)
	│                             │
	└──────────────┬──────────────┘
				   ▼
			 HTTP Response

Project Structure

RateLimiter/
├── Core/
│   ├── IRateLimiter.cs
│   ├── IRateLimitStrategy.cs
│   ├── IRuleProvider.cs
│   ├── DefaultRateLimiter.cs
│   ├── LoggingRateLimiterDecorator.cs
│   ├── RateLimitStrategyFactory.cs
│   ├── Models/
│   │   ├── RateLimitRequest.cs
│   │   ├── RateLimitRule.cs
│   │   ├── RateLimitResult.cs
│   │   └── RateLimiterOptions.cs
│   └── Exceptions/
│       └── RateLimitException.cs
│
├── Algorithms/
│   ├── TokenBucketStrategy.cs
│   ├── DistributedTokenBucketStrategy.cs
│   ├── FixedWindowStrategy.cs
│   ├── SlidingWindowStrategy.cs
│   └── LeakyBucketStrategy.cs
│
├── Infrastructure/
│   ├── IRateLimitRepository.cs
│   ├── InMemoryRateLimitRepository.cs
│   ├── RedisRateLimitRepository.cs
│   ├── Logging/
│   │   └── SerilogConfiguration.cs
│   └── Exceptions/
│       └── RedisConnectionException.cs
│
├── RuleEngine/
│   └── JsonRuleProvider.cs
│
├── Middleware/
│   └── RateLimitingMiddleware.cs
│
├── Controllers/
│   ├── TestController.cs
│   └── AdminController.cs
│
├── Monitoring/
│   └── MetricsService.cs
│
├── Program.cs
├── appsettings.json
└── RateLimiter.csproj

Getting Started

Prerequisites

  • .NET 10 SDK
  • Redis (optional, for distributed deployments)
  • Visual Studio 2026 or VS Code

Installation

  1. Clone or navigate to the workspace
  2. Restore packages:
dotnet restore
  1. Build the solution:
dotnet build

Configuration

appsettings.json

{
  "RateLimiter": {
	"DefaultAlgorithm": "TokenBucket",
	"Rules": [
	  {
		"RuleId": "user_limit",
		"Property": "User",
		"Limit": 100,
		"Window": "00:01:00",
		"Algorithm": "TokenBucket",
		"Priority": 1,
		"Enabled": true
	  },
	  {
		"RuleId": "ip_limit",
		"Property": "IP",
		"Limit": 1000,
		"Window": "00:01:00",
		"Algorithm": "FixedWindow",
		"Priority": 10,
		"Enabled": true
	  }
	]
  },
  "Redis": {
	"Enabled": false,
	"ConnectionString": "localhost:6379",
	"Ssl": false,
	"AbortOnConnectFail": false
  },
  "Serilog": {
	"MinimumLevel": "Information",
	"WriteTo": [ ... ]
  }
}

Supported Properties

  • User: Limit by authenticated user ID
  • IP: Limit by client IP address
  • Client: Limit by X-Client-Id header
  • Custom: Any custom identifier

Algorithms

Token Bucket

  • Best for: Bursting traffic patterns, AWS-like behavior
  • In-Memory: LocalTokenBucketStrategy
  • Distributed: DistributedTokenBucketStrategy (Redis + Lua)
  • Characteristics: Allows bursts, smooth refill

Fixed Window

  • Best for: Simple rate limiting
  • Characteristics: Counter resets every window period
  • Issue: Boundary problem (spike at window edges)

Sliding Window Log

  • Best for: Accurate limiting
  • Characteristics: Keeps log of all requests in window
  • Trade-off: Higher memory usage

Leaky Bucket

  • Best for: Smooth traffic control
  • Characteristics: Requests leak at constant rate
  • Issue: Cannot burst

Running the Application

Local Development (In-Memory)

dotnet run --project RateLimiter.csproj

The application will:

With Redis (Distributed)

  1. Start Redis:
docker run -d -p 6379:6379 redis:latest
  1. Update appsettings.json:
{
  "Redis": {
	"Enabled": true,
	"ConnectionString": "localhost:6379"
  }
}
  1. Update Program.cs to register RedisRateLimitRepository and DistributedTokenBucketStrategy

  2. Run:

dotnet run --project RateLimiter.csproj

API Endpoints

Test Endpoint

GET /api/test

Returns: { "message": "ok" }

Response Headers:

  • X-RateLimit-Limit: Max requests allowed
  • X-RateLimit-Remaining: Remaining requests
  • Retry-After: Seconds to wait (on rate limit)

Admin Endpoints

Get All Rules

GET /api/admin/rules

Get Specific Rule

GET /api/admin/rules/{ruleId}

Create Rule

POST /api/admin/rules
Content-Type: application/json

{
  "ruleId": "new_rule",
  "property": "User",
  "limit": 50,
  "window": "00:01:00",
  "algorithm": "TokenBucket",
  "priority": 5,
  "enabled": true
}

Update Rule

PUT /api/admin/rules/{ruleId}
Content-Type: application/json

{
  "limit": 75,
  "enabled": false
}

Delete Rule

DELETE /api/admin/rules/{ruleId}

Metrics

GET /api/admin/metrics
GET /metrics (Prometheus endpoint)

Rate Limit Response

Success (200 OK)

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 47

Rate Limited (429 Too Many Requests)

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Retry-After: 30

{
  "message": "Rate limit exceeded",
  "retryAfter": 30
}

Testing

Run All Tests

dotnet test

Run Unit Tests Only

dotnet test --filter "Category=Unit"

Run Integration Tests Only

dotnet test --filter "Category=Integration"

Test Coverage

Unit Tests:

  • TokenBucketStrategy
  • FixedWindowStrategy
  • SlidingWindowStrategy
  • LeakyBucketStrategy
  • InMemoryRateLimitRepository
  • RateLimitStrategyFactory

Integration Tests:

  • Middleware behavior
  • Rule loading
  • Admin endpoints
  • End-to-end flows

Monitoring

Prometheus Metrics

Available at: http://localhost:5000/metrics

Counters:

  • ratelimit_allowed_requests_total: Total allowed requests
  • ratelimit_blocked_requests_total: Total blocked requests
  • ratelimit_errors_total: Total errors

Gauges:

  • ratelimit_active_keys: Current number of tracked keys

Histograms:

  • ratelimit_request_duration_seconds: Request processing duration

Logging

Logs are written to:

  • Console (formatted JSON)
  • File: logs/ratelimiter-YYYY-MM-DD.txt

Log format:

{
  "Timestamp": "2024-01-15T10:30:45.123Z",
  "Level": "Information",
  "Message": "RateLimit decision: Allowed=true Remaining=47 Limit=100 RetryAfter=0",
  "Application": "RateLimiter",
  "MachineName": "DESKTOP-ABC"
}

Design Patterns Used

Strategy Pattern

Algorithms can be swapped without changing application code.

Factory Pattern

RateLimitStrategyFactory creates appropriate strategy instances.

Repository Pattern

IRateLimitRepository abstracts data store (in-memory or Redis).

Decorator Pattern

LoggingRateLimiterDecorator adds logging without modifying core logic.

Dependency Injection

ASP.NET Core DI container manages all service lifetimes.

Performance Characteristics

Algorithm Memory Accuracy Supports Burst Time Complexity
Token Bucket Low High Yes O(1)
Fixed Window Very Low Medium No O(1)
Sliding Window Log Medium-High Very High No O(n)
Leaky Bucket Low High No O(1)

Deployment

Docker

FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY . .
EXPOSE 5000
ENV ASPNETCORE_URLS=http://+:5000
CMD ["dotnet", "RateLimiter.dll"]

Build and run:

docker build -t rate-limiter:latest .
docker run -p 5000:5000 -e Redis__Enabled=true rate-limiter:latest

Kubernetes

Environment variables:

env:
  - name: Redis__Enabled
	value: "true"
  - name: Redis__ConnectionString
	value: "redis-service:6379"
  - name: ASPNETCORE_ENVIRONMENT
	value: "Production"

Environment Variables

  • ASPNETCORE_ENVIRONMENT: Development, Staging, Production
  • Redis__Enabled: true/false
  • Redis__ConnectionString: Redis connection string
  • Logging__LogLevel__Default: Debug, Information, Warning, Error

Best Practices

  1. Choose the Right Algorithm

    • Use Token Bucket for APIs with burst traffic
    • Use Fixed Window for simple rate limiting
    • Use Sliding Window for very accurate limiting
  2. Set Appropriate Limits

    • Monitor usage patterns before setting limits
    • Use admin API to adjust dynamically
    • Set priority for rule matching order
  3. Monitoring

    • Enable Prometheus metrics in production
    • Monitor blocked request count
    • Set up alerts for error spikes
  4. Failover

    • If Redis unavailable, Redis repository logs error
    • Middleware fails open (allows request)
    • Application continues working
  5. Security

    • Protect admin endpoints with authentication
    • Validate X-Client-Id header sources
    • Use TLS for Redis connections in production

Troubleshooting

High Memory Usage

  • Check if Sliding Window strategy is used
  • Monitor active keys count in Prometheus
  • Consider switching to Token Bucket or Fixed Window

Rate Limits Not Working

  • Check rule.Enabled = true
  • Verify rule.Property matches request (User, IP, Client)
  • Check appsettings.json configuration
  • View logs for matching decisions

Redis Connection Errors

  • Verify Redis is running
  • Check ConnectionString in appsettings.json
  • Ensure firewall allows port 6379
  • Check Redis logs

Example Usage

cURL

Check rate limit:

curl -i http://localhost:5000/api/test \
  -H "X-Client-Id: client123"

View rules:

curl http://localhost:5000/api/admin/rules

Create rule:

curl -X POST http://localhost:5000/api/admin/rules \
  -H "Content-Type: application/json" \
  -d '{
	"ruleId": "api_limit",
	"property": "IP",
	"limit": 50,
	"window": "00:01:00",
	"algorithm": "TokenBucket",
	"priority": 1,
	"enabled": true
  }'

C# Client

using (var client = new HttpClient())
{
	client.DefaultRequestHeaders.Add("X-Client-Id", "client123");

	var response = await client.GetAsync("http://localhost:5000/api/test");

	if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
	{
		var retryAfter = response.Headers.GetValues("Retry-After").First();
		Console.WriteLine($"Rate limited. Retry after {retryAfter} seconds");
	}
}

Contributing

  1. Create feature branch
  2. Add/update tests
  3. Ensure all tests pass
  4. Submit pull request

License

MIT License - See LICENSE file for details

Support & Documentation

  • Full source code comments and XML docs
  • RateLimiter.md for detailed specifications
  • Test project for usage examples
  • Admin API for real-time rule management

Technology Stack

  • .NET 10
  • ASP.NET Core 10
  • StackExchange.Redis 2.7.27
  • Serilog 4.1.1
  • Prometheus.NET 8.2.1
  • xUnit 2.9.3
  • FluentAssertions 6.12.0
  • Moq 4.20.70

Roadmap

  • Circuit breaker pattern
  • Advanced analytics dashboard
  • Machine learning-based limit adjustment
  • GraphQL admin API
  • WebSocket support
  • Rate limit sharing between services
  • Multi-region failover

Version: 1.0.0
Last Updated: 2024
Author: Rate Limiter Team

About

RateLimiter

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages