Skip to content

Yash-Raj-5424/FluxWard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FluxWard

A production-grade API rate limiter built with Java 21, Spring Boot 4.x, and Redis. FluxWard supports multiple rate limiting algorithms, per-route configuration, dynamic rule management, JWT-based client identification, circuit breaking, metrics, and abuse prevention.


Table of Contents


Architecture

HTTP Request
    │
    ▼
RateLimitFilter (OncePerRequestFilter)
    │── Block/Allow check → 403 / pass-through
    │── Rate limit check
    ▼
RateLimiterService
    │── RouteRuleResolver (client rule → dynamic route → YAML → global default)
    │── KeyExtractorResolver (API_KEY / IP / JWT_SUBJECT)
    │── CircuitBreakerRedisStore (Resilience4j wraps Redis calls)
    │       └── AlgorithmFactory → TokenBucket / FixedWindow / SlidingWindow
    │               └── RedisRateLimitStore (Lua scripts)
    │── RateLimitMetrics (Micrometer counters + timers)
    └── RateLimitEventPublisher (Spring events → async Redis storage)

Architecture Diagram

Features

  • Three algorithms — Token Bucket, Fixed Window, Sliding Window Counter
  • Per-route config — each route can override algorithm, capacity, windowMs, keyType
  • Dynamic rules — update route/client rules at runtime via Admin API without restart
  • Client-level overrides — specific clients can have custom rate limits
  • JWT support — extract client identity from JWT subject claim
  • Circuit breaker — Resilience4j wraps Redis calls, falls back to in-memory on failure
  • Metrics — Micrometer counters and timers exposed at /actuator/prometheus
  • Block/Allowlist — permanently block or whitelist clients
  • Rate limit events — every decision stored in Redis, queryable via Admin API
  • Health indicator — Redis status, circuit breaker state, and active rules at /actuator/health
  • Configuration validation — fails fast on startup with clear error messages

Setup

Prerequisites

  • Java 21
  • Redis 7+
  • Maven 3.8+

Run

# Start Redis
redis-server

# Run the app
mvn spring-boot:run

Build

mvn clean install

Configuration

All options go under rate-limiter in application.yml:

rate-limiter:
  capacity: 100                          # global token capacity
  refill-rate-per-second: 10             # tokens refilled per second (token bucket)
  window-ms: 60000                       # window size in milliseconds
  fail-open: true                        # allow requests when Redis is down
  key-type: API_KEY                      # API_KEY | IP | JWT_SUBJECT
  algorithm: TOKEN_BUCKET                # TOKEN_BUCKET | FIXED_WINDOW | SLIDING_WINDOW
  jwt:
    secret: "your-secret-key-32-chars-min"
  routes:
    - path: /api/login/**
      algorithm: FIXED_WINDOW
      capacity: 10
      window-ms: 60000
      key-type: API_KEY
    - path: /api/search/**
      algorithm: SLIDING_WINDOW
      capacity: 30
      window-ms: 10000
      key-type: JWT_SUBJECT

admin:
  username: admin
  password: your-admin-password

resilience4j:
  circuitbreaker:
    instances:
      redis:
        sliding-window-size: 10
        failure-rate-threshold: 50
        wait-duration-in-open-state: 10s
        permitted-number-of-calls-in-half-open-state: 3
        sliding-window-type: COUNT_BASED

management:
  endpoints:
    web:
      exposure:
        include: health, prometheus, ratelimiter
  endpoint:
    health:
      show-details: always

Configuration fields

Field Type Default Description
capacity int 100 Max tokens / requests per window
refill-rate-per-second double 10 Token refill rate (token bucket only)
window-ms long 60000 Window size in milliseconds
fail-open boolean true Allow traffic when Redis is down
key-type string API_KEY Client identification method
algorithm enum TOKEN_BUCKET Rate limiting algorithm
jwt.secret string HMAC-SHA256 secret (min 32 chars)

API Endpoints

Test endpoints

Method Path Description
GET /test Token bucket (global default)
GET /test/fixedwindow Fixed window
GET /test/slidingwindow Sliding window (JWT auth)

Headers:

X-API-Key: your-api-key
Authorization: Bearer <jwt-token>   # for JWT routes

Response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1234567890

429 response:

{"error": "rate_limit_exceeded", "retryAfterMs": 1000}

403 response (blocked):

{"error": "client_blocked", "clientKey": "test123"}

Admin API

All admin endpoints require Basic Auth (admin / your password).

Route rules

Method Path Description
PUT /admin/routes/{path} Save dynamic route rule
GET /admin/routes List all dynamic route paths
GET /admin/routes/{path} Get rule for a path
DELETE /admin/routes/{path} Delete dynamic route rule

PUT /admin/routes/{path} request body:

{
    "algorithm": "FIXED_WINDOW",
    "capacity": 10,
    "windowMs": 60000,
    "refillRatePerSecond": 1.0,
    "keyType": "API_KEY"
}

Client rules

Method Path Description
PUT /admin/clients/{clientKey} Save client-specific rule
GET /admin/clients/{clientKey} Get client rule
DELETE /admin/clients/{clientKey} Delete client rule

Block / Allowlist

Method Path Description
POST /admin/block/{clientKey} Block a client (returns 403)
DELETE /admin/block/{clientKey} Unblock a client
GET /admin/blocked List all blocked clients
POST /admin/allow/{clientKey} Allowlist a client (bypasses rate limiting)
DELETE /admin/allow/{clientKey} Remove from allowlist
GET /admin/allowed List all allowlisted clients

Events

Method Path Description
GET /admin/events?limit=50 Get recent events
GET /admin/events/{clientKey} Get events for a client
DELETE /admin/events Clear all events

Event response:

[
    "{\"clientKey\":\"test123\",\"route\":\"/test\",\"algorithm\":\"TOKEN_BUCKET\",\"type\":\"ALLOWED\",\"timestamp\":\"2026-05-05T10:00:00Z\"}"
]

Actuator endpoints

Path Description
/actuator/health App health with Redis, circuit breaker, and rule counts
/actuator/prometheus Micrometer metrics in Prometheus format
/actuator/ratelimiter Current rate limiter config per route

Algorithms

Token Bucket

  • Tokens refill continuously at refillRatePerSecond
  • Allows bursting up to capacity
  • Best for: general API rate limiting with burst tolerance

Fixed Window

  • Hard counter reset at each window boundary
  • Simple and predictable
  • Best for: login endpoints, strict per-minute limits
  • Note: allows 2x burst at window boundary

Sliding Window Counter

  • Blends current and previous window counts by elapsed time
  • Smoother than fixed window, no boundary burst
  • Best for: search endpoints, smooth traffic shaping

Rule Resolution Order

For every request, FluxWard resolves the rule in this order:

  1. Client-specific rulefluxward:client:{clientKey} in Redis
  2. Dynamic route rulefluxward:route:{path} in Redis (exact match)
  3. YAML route rulerate-limiter.routes (Ant-path match)
  4. Global defaultrate-limiter.* global config

Phase Summary

Phase Features
Phase 1 Token bucket algorithm, Redis Lua script, in-memory fallback, API key extraction
Phase 2 Fixed window + sliding window algorithms, per-route config, algorithm strategy pattern
Phase 3 Micrometer metrics, Resilience4j circuit breaker, JWT extraction, per-route key type, custom actuator endpoint
Phase 4 Admin API, dynamic route/client rules, Basic Auth security
Phase 5 Block/allowlist, rate limit events, async event listener, events admin API
Phase 6 Health indicator, configuration validation, README

About

A Distributed API Rate Limiter

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors