Katkat

Implement a rate limiter at scale

MicrosoftSoftware Engineer · Onsite

Last updated

This problem tests your ability to implement an efficient, thread-safe rate limiter using a sliding window algorithm to ensure a request quota is enforced across a distributed environment.

Problem: Scalable Rate Limiter

Design a rate limiter class that restricts the number of requests a user can make within a specified time window. You must implement the following interface:

class RateLimiter:
    def __init__(self, max_requests: int, window_seconds: int):
        """Initializes the limiter with a capacity and time window."""

    def is_allowed(self, user_id: str) -> bool:
        """Returns True if the request is allowed, False otherwise."""

Requirements

  1. Sliding Window: Use a sliding window approach (or an approximation like a token bucket) to ensure requests are spread out correctly, rather than resetting at fixed intervals.
  2. Concurrency: The implementation must be thread-safe for a single-node environment.
  3. Scale: Describe how you would handle this in a distributed system where multiple application servers share the rate limit state for a single user.

Examples

  • Example 1: max_requests = 2, window_seconds = 10
    • is_allowed("user1") -> True (Count: 1)
    • is_allowed("user1") -> True (Count: 2)
    • is_allowed("user1") -> False (Over capacity)
    • Wait 10 seconds -> is_allowed("user1") -> True

Constraints

  • max_requests will be up to 10,000.
  • window_seconds will be between 1 and 3600.
  • The solution should have an O(1) time complexity per call on average.

Considerations

  • How will you store timestamps for each user?
  • How do you handle expired timestamps to keep memory usage low?

Hints

Hint 1

Consider using a deque (double-ended queue) for each user to store the timestamps of individual requests.

Hint 2

When a new request arrives, remove all timestamps from the front of the user's deque that are older than the current time minus the window duration.

Hint 3

For distributed systems, consider using a centralized data store like Redis to maintain the request logs or use the 'INCR' and 'EXPIRE' commands for atomic window tracking.

Follow-up questions

  • How would you handle the 'thundering herd' problem if a rate limit reset happens for thousands of users simultaneously?
  • How does your solution change if you need to support multiple different rate limits (e.g., 100 requests per minute AND 5000 requests per hour)?
  • What specific trade-offs exist between using a Fixed Window algorithm versus a Token Bucket algorithm?