The Interview Prompt

The interviewer just said…

“Design an in-memory rate limiter.”

You have a whiteboard (or a shared doc) and roughly 45 minutes. This is a Low-Level Design (LLD) prompt — not a distributed-systems deep dive on Redis Cluster. The interviewer wants to see how you clarify scope, model configs and results, define a Strategy interface, and implement at least one algorithm correctly under concurrency.


What you should do next

Pause. Do not open with “I’ll use Redis with a Lua script.” That jumps past requirements and signals infrastructure before domain.

Your first move is conversational:

  1. Acknowledge the prompt.
  2. Ask clarifying questions (next chapter).
  3. State what you will deliver in the time box: requirements, entities, Strategy + Manager APIs, one solid algorithm (usually Token Bucket), thread-safety story, and — if time allows — how you’d go multi-node later.

That sequence mirrors the classic LLD delivery framework: LLD delivery in a hurry.


What this course promises

By the end you will have walked the working Java project in hub/scripts/rate-limiter-sourced/ — not slideware. The domain matches what you’d whiteboard:

  • Config / Result / Type — immutable values and an algorithm enum
  • Strategy + Factory + Manager — pluggable algorithms, one entry point
  • Algorithms: Token Bucket, Fixed Window, Sliding Window Log/Counter, Leaky Bucket
  • Thread safety: ConcurrentHashMap + per-client synchronized state
  • Scale-out sketches: Redis INCR/EXPIRE, Redis Lua, DB row lock

A shorter classic problem write-up also lives on the LLD track: Rate Limiter — Request Throttling. This course is the interview → project path against the code.


A 60-second preview of the end state

Main.java bootstraps a manager and hits APIs:

RateLimiterManager manager = new RateLimiterManager(globalDefault);
manager.registerApi("/api/search", searchConfig);
manager.registerClientOverride("/api/search", "premium", premiumConfig);

RateLimitResult r = manager.hit("/api/search", "user123");
if (!r.isAllowed()) {
    // retry after r.getRetryAfterMs()
}

That’s the shape: hit(api, client) → allow or reject with remaining quota.