MindForge
MindForge
DashboardHelp & Support
Dashboard
MindForge

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
Design a Rate Limiter
Course contents

Interview Preparation Bootcamp

Course progress

0%
0 of 177 modules complete
Start Here0/1
  • How to Use This Course
Data Structures & Algorithms0/27
  • Arrays and Hashing
  • Two Pointers
  • Sliding Window
  • Sliding Window: Harder Problems
  • Binary Search
  • Stacks
  • Practice Test: Arrays, Pointers, Windows, Search and Stacks
  • Trees: Traversals and Core Patterns
  • Binary Search Trees and Rebuilding a Tree
  • Tries (Prefix Trees)
  • Heaps and Priority Queues
  • Graphs: BFS and DFS
  • Topological Sort and Cycle Detection
  • Union-Find (Disjoint Set Union)
  • Practice Test: Trees, Heaps and Graphs
  • Dynamic Programming Basics
  • Dynamic Programming: Two Dimensions
  • Dynamic Programming: Hard String Matching
  • Backtracking
  • Backtracking: Constraint Satisfaction
  • Greedy Algorithms
  • Interval Problems
  • Bit Manipulation
  • Math and Geometry
  • String Manipulation
  • Pattern Recall and Mock Coding Rounds
  • Practice Test: DP, Backtracking, Greedy and More

System Design

Foundations0/16
  • The System Design Interview Framework
  • Back-of-the-Envelope Estimation
  • Networking and Protocols for Design
  • API Design and Idempotency
  • Load Balancing, Proxies, and Scaling Out
  • Caching and CDNs
  • Choosing a Database: Storage, Indexes and Transactions
  • Replication, Partitioning, and Sharding
  • CAP, PACELC, and Levels of Consistency
  • Messaging, Queues, and Event-Driven Architecture
  • Distributed Transactions and Data Integrity
  • Coordination, Consensus, and Distributed Locks
  • Reliability, Resilience, and Rate Limiting
  • Observability, Security, and Cost
  • System Design Cheat Sheet
  • Practice Test: System Design Foundations
Case Studies0/23
  • Design a URL Shortener
  • Design a Rate Limiter
  • Design a Notification Service
  • Design a Job Queue System
  • Design a Chat App (WhatsApp)
  • Design an Analytics Pipeline
  • Design a Multi-tenant SaaS Architecture
  • Design a Social Media Feed (Twitter/X)
  • Design a Search Autocomplete System
  • Design a File Storage Service (Dropbox)
  • Design Google Docs
  • Design a Code Review System
  • Design Netflix
  • Design YouTube
  • Design Spotify
  • Design Uber/Lyft
  • Design Airbnb
  • Design Ticketmaster (Eventbrite)
  • Design an E-commerce Cart, Checkout, and Catalog
  • Design a Payment System
  • Design a Logging and Monitoring System
  • Mock Design Rounds
  • Practice Test: System Design Case Studies
Low-Level Design0/19
  • The LLD Interview Framework and UML
  • OOP Foundations for Design
  • SOLID Principles
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns I — Strategy, Observer, Command, State, Template Method
  • Behavioral Patterns II and Anti-Patterns
  • Concurrency in Low-Level Design
  • Design a Parking Lot
  • Design an Elevator System
  • Design a Movie Ticket Booking System
  • Design an Expense-Sharing App (Splitwise)
  • Design a Vending Machine and an ATM
  • Design a Rate Limiter and a Logging Framework
  • Design a Notification Service and an In-Memory Cache
  • Design Games — Tic-Tac-Toe, Snake and Ladder, Chess
  • Database Design for LLD
  • LLD Cheat Sheet and Recall Drill
  • Practice Test: Low-Level Design

Backend

Python0/5
  • How Python Runs Your Code
  • Functions Deep Dive: Closures, Generators, Context Managers, Scope
  • Classes Deep Dive: Method Types, MRO, Metaclasses
  • Standard Library and Serialization
  • Practice Test: Python
Django0/6
  • Django Request Lifecycle
  • Lab: Django Middleware — Request ID & Response Time
  • Django ORM and Querysets
  • Django's Cache Framework
  • Practice Test: Django
  • Django in Production: Debugging Labs
FastAPI0/5
  • FastAPI, ASGI, and Async
  • FastAPI Dependency Injection
  • FastAPI Background Tasks
  • Lab: FastAPI Async — Concurrent Aggregation
  • Practice Test: FastAPI
Databases (PostgreSQL)0/6
  • Indexing
  • Query Optimization
  • Transactions and Isolation
  • Migrations and Schema Changes
  • Hierarchical Data and Safe Concurrent Updates
  • Practice Test: Databases
Caching, Queues & Distributed Systems0/8
  • Redis Caching
  • Redis Advanced Patterns
  • Celery and Background Workers
  • Kafka and Message Queues
  • Async Pipelines
  • Distributed Systems Basics
  • Distributed Locks
  • Practice Test: Caching, Queues and Distributed Systems
APIs, Security & Deployment0/9
  • REST API Design
  • API Versioning and Error Handling
  • API Security and Authentication
  • WebSockets and Real-Time Systems
  • Docker and Containers
  • File Storage with S3
  • Testing Strategies
  • Mock Backend Round
  • Practice Test: APIs, Security and Deployment
Frontend0/38
  • HTML Document Structure and Semantics
  • CSS Box Model, Flexbox and Grid
  • CSS Architecture and Theming
  • CSS and Rendering Performance
  • Variables, Scope, Hoisting, and Truthiness
  • Functions, this, and Binding
  • Objects and Prototypal Inheritance
  • JavaScript Utility Patterns: Cloning, Caching, and Memory
  • Promises From Scratch
  • The Event Loop and Browser Rendering Pipeline
  • The DOM: Nodes, Events, and Traversal
  • Practice Test: HTML, CSS and JavaScript
  • React Rendering Fundamentals
  • React Hooks Internals
  • React Performance
  • Lab: React — Stateful Counter Component
  • State Management
  • State Machines in React
  • React Custom Hooks and Composition Patterns
  • TypeScript for React
  • React Testing
  • Practice Test: React
  • HTTP and Caching
  • Network Performance and Web Vitals
  • Code Splitting and Bundles
  • Virtualization
  • GraphQL and Data Fetching
  • Web Security
  • WebSockets and Real-time
  • SSR and Next.js
  • Micro-frontends
  • Build Tools and Bundling
  • Accessibility
  • Error Handling
  • Internationalization
  • Animation
  • Rapid Recall and Mock Frontend Rounds
  • Practice Test: Performance, Architecture and Production
Behavioral & Interview Day0/14
  • Resume and Project Walkthroughs
  • The STAR Method and Refining Your Stories
  • Conflict and Difficult Coworkers
  • Failures, Incidents, and Obstacles
  • Leadership, Mentorship, and Ownership
  • Teamwork, Communication, and Feedback
  • Growth and Handling Ambiguity
  • Career Goals, Why This Company, and Negotiation
  • Situational Questions
  • Company Research
  • Mock Behavioral Rounds
  • Interview Day
  • After the Interview
  • Practice Test: Behavioral and Interview Day
Browsing without an account — progress is saved in this browser only.Sign in to save it

Design a Rate Limiter

System Design60 min
Sign in to open the interactive design canvas for this exercise.

A rate limiter caps how many requests one client (a user, an API key, or an IP address) can make in a time window. It sits at the edge, before requests reach your backend, and protects you from abuse, runaway retries, and surprise cloud bills.

This question is less about drawing boxes and more about comparing algorithms and picking one with a reason. Interviewers use it to check whether you understand the difference between a textbook counter and something that survives 50 gateway instances running at once.

Requirements

Functional requirements

  • Limit requests per identity (user ID, API key, or IP) to N requests per time window.
  • Return 429 Too Many Requests with a Retry-After header when the limit is hit.
  • Support different limits per plan (free vs. paid).

Non-functional requirements

  • Accuracy costs latency: a perfectly precise limiter needs coordination between servers, which is slower. An approximate limiter is faster but may let a small burst through.
  • The limiter check itself must add only single-digit milliseconds.
  • It must work correctly across a fleet of stateless gateway instances, not just on one machine.
  • It must fail in a predictable way if its counter store goes down. Usually fail open (let requests through) for availability, fail closed (reject) for security-critical endpoints.

Remember: a rate limiter that only works correctly on one server is not a rate limiter, it's a demo. The real question is always "does this hold up across a fleet?"

Sign in to try this knowledge check.

The five algorithms, and how to picture each one

Fixed window counter. Picture a whiteboard tally that gets erased every minute on the clock. Simple, O(1) memory, but a client can send N requests at 0:59 and another N at 1:00, getting 2N requests in two seconds right at the boundary.

Sliding window log. Picture keeping every receipt, then on each check throwing away receipts older than the window and counting what's left. Perfectly accurate, no boundary burst, but memory grows with request volume and each check costs more (you're storing every timestamp).

Sliding window counter. Picture two overlapping buckets: last window's count and this window's count, blended by how much of the previous window still overlaps "now." estimated_count = current_window_count + previous_window_count × (1 - elapsed_fraction_of_current_window) Near-accurate, O(1) memory, cheap to compute. This is the industry-favored answer (Cloudflare and Stripe-style gateways use it) because it balances accuracy and cost.

Token bucket. Picture a prepaid wallet. Every request spends one credit; credits refill at a steady rate up to a cap. This naturally allows a burst up to the bucket's size while still capping sustained abuse, which matches how real APIs behave: a page load firing 10 requests at once is fine, sustained hammering isn't.

Leaky bucket. Picture a queue draining at a constant speed. Requests join the back of the queue; if the queue is full, new ones are dropped. This smooths bursty traffic into a steady outflow, useful when the thing behind you can't handle spikes at all, but legitimate bursts get delayed instead of allowed.

Token bucket and leaky bucket are mirror images: one grants credit that drains over time, the other drains a fixed-rate queue in the opposite direction. If you can explain one, you can derive the other on a whiteboard.

Algorithm Tracks Allows bursts Memory Best for
Fixed window count + reset time yes, at the boundary O(1) Simple counters
Sliding window log every timestamp no O(n) Precise enforcement
Sliding window counter two window counts partially O(1) Distributed systems
Token bucket credits yes O(1) API rate limiting
Leaky bucket queue depth no O(1) Traffic shaping

The interview-favored pick: token bucket, or the sliding window counter, for API gateways. Bursts are normal client behavior, and you want to allow that while still capping sustained abuse.

Remember: token bucket lets bursts through and caps the average; fixed window is simple but leaks double the limit at the boundary.

Sign in to try this knowledge check.

Where to store counters: Redis vs. in-memory

In-memory (per instance) Redis (shared)
Accuracy across a fleet Wrong: N instances effectively multiply the limit by N Correct: one shared source of truth
Latency Fastest, no network hop About 1ms extra for the round trip
Survives a restart No Yes
Complexity Simple Needs a Redis cluster plus a TTL/eviction plan

In-memory only works if you pin a client to one gateway instance forever, which is fragile and breaks the moment you scale up or down. For a real distributed gateway, use Redis: INCR key with EXPIRE, or a Lua script so the check-and-increment happens in one atomic round trip. That avoids a race where two concurrent requests both see "under limit" before either one increments.

The Redis primitive follows the algorithm:

  • Fixed window: INCR ratelimit:{key}:{window}, with EXPIRE set only on the first increment. The key self-cleans via TTL.
  • Sliding window log: ZADD the timestamp into a sorted set, ZREMRANGEBYSCORE to drop anything older than now - window, then ZCARD to count. Wrap all three in one Lua script so nothing interleaves.
  • Sliding window counter: two plain INCR keys, one per window. Read both, apply the weighted formula above. No Lua needed for reads.
-- Redis Lua script sketch for token bucket
local tokens = tonumber(redis.call('GET', KEYS[1]) or capacity)
local now = tonumber(ARGV[2])
-- refill based on elapsed time, then attempt to consume 1 token
if tokens >= 1 then
  redis.call('SET', KEYS[1], tokens - 1, 'EX', ttl)
  return 1  -- allowed
else
  return 0  -- rejected
end

API

Config per tier:
  { tier: "free", limit: 100, window_seconds: 60 }
  { tier: "pro",  limit: 10000, window_seconds: 60 }

Every incoming request:
  key = f"ratelimit:{user_id}:{current_window}"
  allowed = check_and_increment(key, limit)
  if not allowed:
    return 429, headers: { "Retry-After": seconds_until_reset }

High-level design

Client --> API Gateway (stateless, N instances)
                 |
                 v
           Rate Limiter Middleware  <--->  Redis Cluster (counters, TTL per key)
                 |
                 v (if allowed)
           Backend Services

The limiter is middleware, not a separate network hop. It runs inline in the gateway's request path, calls Redis synchronously before forwarding the request, and Redis is the one shared truth every gateway instance checks. TTLs on every key mean old counters clean themselves up.

Deep dives

What breaks when you go distributed?

  • Race conditions. Two concurrent requests from the same client can both read "count = 9, limit = 10" before either writes, letting both through. Fix it with an atomic Redis operation (INCR, or a Lua script) instead of a separate read then write.
  • Redis as a single point of failure. If Redis goes down, decide up front: fail open (allow everything, risk overload) or fail closed (reject everything, risk false 429s for real users). Most production gateways fail open and lean on other safeguards, like autoscaling and circuit breakers, as a backstop.
  • Clock skew across regions. Wall-clock-based windows can drift slightly when gateway instances span regions. Sliding window algorithms tolerate this better than fixed windows.
  • Multi-region counters. A true global limit across regions needs either one global Redis (adds cross-region latency) or per-region limits that roughly sum to the global target (simpler, eventually consistent, usually good enough).
Sign in to try this knowledge check.

Trade-offs and follow-up questions

Sharding counters across a Redis Cluster scales horizontally, but one very abusive client still hammers a single shard. That's usually fine, since it's one client's traffic, not global traffic.

Add a local "fast reject" cache: if a client is already known to be far over the limit, reject it without even calling Redis, saving a network hop on the abuse case. Also return rate-limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) so well-behaved clients can throttle themselves before hitting the wall.

Q: How do you avoid a race condition when two requests arrive at nearly the same instant? A: Use an atomic operation: Redis INCR or a Lua script that reads, checks, and writes in one round trip, so nothing can interleave.

Q: What happens if Redis is temporarily unreachable? A: Decide and document the failure mode up front. Fail-open protects availability but risks abuse during the outage; fail-closed protects backends but causes false rate-limit errors. Most gateways fail open and rely on other safeguards.

Q: How would you rate-limit anonymous IP traffic differently from authenticated API-key traffic? A: Different key prefixes and different configs (ratelimit:ip:{ip} vs. ratelimit:key:{api_key}), typically with the stricter IP-based limit applied first at the edge, and the more generous authenticated limit enforced deeper in the gateway.

Sign in to try this knowledge check.
PreviousDesign a URL ShortenerNextDesign a Notification Service

Course progress

0%
0 of 177 modules complete

On this page

  • Requirements
  • The five algorithms, and how to picture each one
  • Where to store counters: Redis vs. in-memory
  • API
  • High-level design
  • Deep dives
  • What breaks when you go distributed?
  • Trade-offs and follow-up questions