Skip to content

vimalyad/rate-limiter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 

Repository files navigation

🚦 Rate Limiter - Low Level Design (LLD)

A robust, highly extensible, and thread-safe API Rate Limiter built in Java. This system is designed from the ground up adhering strictly to SOLID Principles and enterprise Design Patterns.

It acts as a gateway interceptor, validating if incoming HTTP requests exceed the configured thresholds using highly optimized mathematical algorithms before allowing traffic to hit the core database or application logic.


🏛️ Class Architecture Diagram

The system architecture heavily utilizes Interface Segregation to keep the storage layer decoupled from the math layer, while employing Factories and Builders to manage object creation.

classDiagram
    %% ================= Interfaces & Implementations =================

    class RateLimiter {
        <<interface>>
        +tryAcquire(request: Request): Response
    }
    
    class ApplicationRateLimiter {
        -algorithm: RateLimitAlgorithm
        -keyExtractor: KeyExtractor
        -applicationRepository: ApplicationRepository
        +tryAcquire(request: Request): Response
    }
    RateLimiter <|.. ApplicationRateLimiter : Implements

    %% ================= Request & Response =================
    
    class Request {
        <<interface>>
        +getIpAddress() String
        +getUserId() String
        +getLocation() String
        +getEndpoint() String
    }
    class HttpRequest
    Request <|.. HttpRequest : Implements

    class Response~T~ {
        <<interface>>
        +isRateLimitExceeded() boolean
        +getResponse() T
    }
    class HttpResponse
    Response <|.. HttpResponse : Implements

    %% ApplicationRateLimiter Aggregations & Dependencies
    ApplicationRateLimiter o-- RateLimitAlgorithm : Aggregation (Injects)
    ApplicationRateLimiter o-- KeyExtractor : Aggregation (Injects)
    ApplicationRateLimiter o-- ApplicationRepository : Aggregation (Injects)
    ApplicationRateLimiter ..> Request : Associates
    ApplicationRateLimiter ..> Response : Creates

    %% ================= Algorithms =================
    
    class RateLimitAlgorithm {
        <<interface>>
        +allowRequest(key: String): boolean
    }
    
    class FixedWindowAlgorithm {
        -limit: int
        -windowSizeMillis: long
        -store: FixedWindowStore
        +allowRequest(key: String): boolean
    }
    
    class SlidingWindowLogAlgorithm {
        -limit: int
        -windowSizeMillis: long
        -store: SlidingWindowStore
        +allowRequest(key: String): boolean
    }
    
    RateLimitAlgorithm <|.. FixedWindowAlgorithm : Implements
    RateLimitAlgorithm <|.. SlidingWindowLogAlgorithm : Implements

    %% ================= Storage Layer =================
    
    class FixedWindowStore {
        <<interface>>
        +incrementAndGet(key: String, windowSize: long): long
    }
    
    class SlidingWindowStore {
        <<interface>>
        +addAndGetRecentWindowCount(key: String, now: long, windowStart: long): long
    }
    
    class RateLimitStore {
        <<interface>>
    }
    
    FixedWindowStore <|-- RateLimitStore : Extends
    SlidingWindowStore <|-- RateLimitStore : Extends

    class InMemoryStore {
        -fixedWindowCounters: Map
        -slidingWindowLogs: Map
        +incrementAndGet(key, windowSize)
        +addAndGetRecentWindowCount(key, now, start)
    }
    RateLimitStore <|.. InMemoryStore : Implements

    %% Algorithm to Store relationships (Interface Segregation)
    FixedWindowAlgorithm o-- FixedWindowStore : Aggregation
    SlidingWindowLogAlgorithm o-- SlidingWindowStore : Aggregation

    %% ================= Key Extractors =================
    
    class KeyExtractor {
        <<interface>>
        +extractKey(request: Request): String
    }
    class IpExtractor
    class UserExtractor
    class LocationExtractor
    class EndpointExtractor
    
    KeyExtractor <|.. IpExtractor : Implements
    KeyExtractor <|.. UserExtractor : Implements
    KeyExtractor <|.. LocationExtractor : Implements
    KeyExtractor <|.. EndpointExtractor : Implements

    %% ================= Database / Core App =================
    
    class ApplicationRepository {
        <<interface>>
        +mockApi(): String
    }
    class MockDbCall
    ApplicationRepository <|.. MockDbCall : Implements

    %% ================= Creation (Builders & Factories) =================
    
    class RateLimiterBuilder {
        -algorithmType: String
        -storeType: String
        -extractorType: String
        -limit: int
        -windowSizeMillis: int
        +withAlgorithm(type: String)
        +withStore(type: String)
        +withExtractor(type: String)
        +build(): RateLimiter
    }
    
    class AlgorithmFactory {
        <<static>>
        +createAlgorithm() RateLimitAlgorithm
    }
    class StoreFactory {
        <<static>>
        +getStore() RateLimitStore
    }
    class ExtractorFactory {
        <<static>>
        +getExtractor() KeyExtractor
    }

    RateLimiterBuilder ..> AlgorithmFactory : Uses
    RateLimiterBuilder ..> StoreFactory : Uses
    RateLimiterBuilder ..> ExtractorFactory : Uses
    RateLimiterBuilder ..> ApplicationRateLimiter : Creates

    %% ================= Enums =================
    class AlgorithmType { <<enumeration>> }
    class StoreType { <<enumeration>> }
    class ExtractorType { <<enumeration>> }
    
    AlgorithmFactory ..> AlgorithmType : Uses
    StoreFactory ..> StoreType : Uses
    ExtractorFactory ..> ExtractorType : Uses
Loading

🛠️ Design Patterns Applied

  1. Strategy Pattern: Algorithms (FixedWindow, SlidingWindow) and Extractors (IpExtractor, UserExtractor) are interchangeable behavioral strategies without modifying the core ApplicationRateLimiter.
  2. Builder Pattern: RateLimiterBuilder abstracts the complex configuration logic and prevents the "Telescoping Constructor Anti-Pattern".
  3. Factory Method Pattern: AlgorithmFactory, StoreFactory, and ExtractorFactory handle the instantiation logic, mapping String/Enum configurations to concrete classes.
  4. Proxy / Decorator Pattern: The ApplicationRateLimiter acts as a proxy, verifying the request quota before delegating the call to the underlying ApplicationRepository.

🛡️ SOLID Principles Adherence

  • Single Responsibility (SRP): Math is isolated in the Algorithm classes. Storage locking and thread safety are isolated in the InMemoryStore.
  • Open/Closed (OCP): Adding a RedisStore or a TokenBucketAlgorithm requires creating a new class and adding a switch case in the factory—zero changes to core logic.
  • Liskov Substitution (LSP): Any implementation of RateLimitAlgorithm can seamlessly replace another without the Orchestrator knowing.
  • Interface Segregation (ISP): FixedWindowAlgorithm only depends on FixedWindowStore, not the fat RateLimitStore interface.
  • Dependency Inversion (DIP): The orchestrator depends entirely on abstractions (RateLimitAlgorithm, KeyExtractor), not concrete implementations.

🚀 How to Run the Simulation

This project simulates a high-traffic environment with edge-case scenarios including exact quota exhaustion, rate limit resets via thread sleeping, and user isolation.

Ensure you have Java 17+ installed.

1. Compile the Source Code: Navigate to the root directory (rate-limiter) and compile the classes, ensuring the source path is set correctly:

javac -sourcepath src src/Main.java

2. Run the System: Execute the compiled classes from the root directory:

java -cp src Main

About

A robust, highly extensible, and thread-safe API Rate Limiter built in Java.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages