Build a Sliding Window Rate Limiter

Difficulty: Medium · Category: Rate Limiter · Languages: Java 17, Python 3.11, Go 1.22, Node.js 20, TypeScript 5.x

Sliding Window Rate Limiter

Background

Rate limiting is a critical component of any production system. It protects services from being overwhelmed by too many requests — whether from a single abusive client, a traffic spike, or a denial-of-service attack.

A sliding window rate limiter is more accurate than a fixed-window counter because it avoids the "boundary burst" problem where a client can send 2× the limit by timing requests around a window boundary.

Recommended infrastructure: Redis — its atomic operations and > built-in key expiry make it ideal for high-throughput rate limiting.

How It Works

The platform injects your chosen infrastructure SDK(s) via constructor. For example, if you select Redis:

public class MyRateLimiter implements RateLimiterContract {
    private final RedisClient redis;

    public MyRateLimiter(RedisClient redis) {
        this.redis = redis;
    }
}

See the SDK Docs tab for the full API reference of your chosen system.

Your Task

Implement the RateLimiterContract interface. Your implementation must:

  1. Store all rate-limit state externally (no in-process counters).
  2. Use a sliding window algorithm — not a simple fixed-window counter.
  3. Be thread-safe: concurrent calls for the same user must never allow more requests than the configured limit.
  4. Automatically expire old request data so memory does not grow unbounded.

Interface

public interface RateLimiterContract {
    boolean allowRequest(String userId);
    void configure(int maxRequests, int windowSizeSeconds);
    int getRemainingRequests(String userId);
    void reset(String userId);
}

Method Details

MethodDescription
allowRequestReturns true if the request is within the limit, false otherwise. Each call that returns true counts as a consumed request.
configureSets the maximum number of requests and the window size. May be called multiple times.
getRemainingRequestsReturns how many more requests the user can make in the current window. Never negative.
resetClears all rate-limit data for the given user.

Constraints

Examples

configure(5, 60)          // 5 requests per 60-second window

allowRequest("alice")     → true   (1/5)
allowRequest("alice")     → true   (2/5)
allowRequest("alice")     → true   (3/5)
allowRequest("alice")     → true   (4/5)
allowRequest("alice")     → true   (5/5)
allowRequest("alice")     → false  (rate limited)

getRemainingRequests("alice") → 0
getRemainingRequests("bob")   → 5   (bob hasn't made any requests)

reset("alice")
allowRequest("alice")     → true   (1/5 — counter reset)

Hints

Infrastructure your code runs against

How your solution is graded

Your score combines functional correctness (40%), performance (40%) and code quality (20%).

Practice this problem

Related LLD problems