PrepZone Logo
PrepZone

Design a Rate Limiter

Token bucket and sliding window in one process.

Why this matters

  • Scope — what "Token bucket" covers inside Rate Limiter and what it does not
  • Scope — what "Sliding window" covers inside Rate Limiter and what it does not
  • Scope — what "Per-key limits" covers inside Rate Limiter and what it does not
  • Scope — what "CampusOS API" covers inside Rate Limiter and what it does not
  • In-memory systems test data structures + thread safety together.
Request
Token bucketrefill rate R
Handler
Tokens refill at a fixed rate; each request consumes one token.

CampusOS context

CampusOS is the fictional smart-campus platform used across this track. Treat this module as a real product slice:

Context

  • Belongs to CampusOS — same naming and design vocabulary as parking, library, and booking modules
  • Scope is one JVM — persistence is in-memory or behind a repository interface
  • Goal is a class diagram + core Java that an interviewer can follow in 35–45 minutes
  • Extension paragraph at the end links to System Design when scale exceeds one process

Requirements snapshot

Functional requirements

  • allow(key) returns true/false for each request
  • Support global and per-user/per-IP limits
  • Token bucket allows bursts; sliding window smooths rate
  • Configurable limits and window size
  • Thread-safe under concurrent requests

Non-functional requirements

  • Single JVM, in-process design for this LLD article
  • Core flows testable with in-memory repositories
  • Extension points for new rules without editing central god classes
  • Clear public API on facade/service layer
  • CampusOS extension links to System Design when scale demands distribution

Overview

This CampusOS module designs Rate Limiter as a production-ready in-process service. Read requirements point-by-point before drawing classes.

Token bucket

Points to cover

  • Scope — what "Token bucket" covers inside Rate Limiter and what it does not
  • Classes — name 2–4 classes/interfaces responsible for this slice
  • Flow — step-by-step: trigger → validation → state change → side effect
  • Edge cases — invalid input, concurrent access, empty state, timeout
  • Pattern — Strategy, State, Observer, or Facade if it fits naturally
  • Test hook — one scenario an interviewer will ask you to walk through

Sliding window

Points to cover

  • Scope — what "Sliding window" covers inside Rate Limiter and what it does not
  • Classes — name 2–4 classes/interfaces responsible for this slice
  • Flow — step-by-step: trigger → validation → state change → side effect
  • Edge cases — invalid input, concurrent access, empty state, timeout
  • Pattern — Strategy, State, Observer, or Facade if it fits naturally
  • Test hook — one scenario an interviewer will ask you to walk through

Per-key limits

Points to cover

  • Scope — what "Per-key limits" covers inside Rate Limiter and what it does not
  • Classes — name 2–4 classes/interfaces responsible for this slice
  • Flow — step-by-step: trigger → validation → state change → side effect
  • Edge cases — invalid input, concurrent access, empty state, timeout
  • Pattern — Strategy, State, Observer, or Facade if it fits naturally
  • Test hook — one scenario an interviewer will ask you to walk through

CampusOS API

Points to cover

  • Scope — what "CampusOS API" covers inside Rate Limiter and what it does not
  • Classes — name 2–4 classes/interfaces responsible for this slice
  • Flow — step-by-step: trigger → validation → state change → side effect
  • Edge cases — invalid input, concurrent access, empty state, timeout
  • Pattern — Strategy, State, Observer, or Facade if it fits naturally
  • Test hook — one scenario an interviewer will ask you to walk through
Java
// CampusOS — RateLimiter facade (keep thin)
public final class RateLimiterService {
    private final RateLimiterRepository repository;

    public RateLimiterService(RateLimiterRepository repository) {
        this.repository = repository;
    }

    /** Orchestrate: validate → domain rules → persist → return result */
    public Result handle(Request request) {
        request.validate();
        var domain = DomainModel.from(request);
        domain.applyRules();
        return repository.save(domain);
    }
}

Quick recall

Everything you need if you only revisit this box.

  1. Token bucket — review this slice before mock interviews.
  2. Sliding window — review this slice before mock interviews.
  3. Per-key limits — review this slice before mock interviews.
  4. CampusOS API — review this slice before mock interviews.

CampusOS extension

When this outgrows one JVM

  • Shard inventory or state by campus ID or geographic region
  • Push notifications, payments, and search to dedicated services (System Design track)
  • Use message queues for async side effects (email, analytics)
  • The class diagram you drew here becomes one box on the HLD architecture diagram

Test yourself

Answer these before moving on — recall is what makes it stick.