Message Rate Limiter
AmazonSoftware Engineer · OnsiteLast updated
Design an in-memory message rate limiter that allows or denies messages based on whether a given time window has elapsed since their last accepted occurrence.
Problem Statement
You are tasked with building a message rate limiter for a distributed logging service. The system receives a sequence of log messages accompanied by integer timestamps in non-decreasing order.
Design a class MessageLimiter with the following requirements:
- The constructor initializes the rate limiter with a given
time_window(in seconds). - A method
should_accept_message(timestamp: int, message: str) -> boolchecks whether the incoming message should be accepted or dropped. - A message is accepted (
True) if it has never been seen before, or if at leasttime_windowseconds have passed since the last accepted occurrence of that exact message string. - When a message is accepted, its cooldown period resets starting from
timestamp. - If a message is rejected (
False), its timestamp is ignored, and the cooldown does not reset.
Class Interface
class MessageLimiter:
def __init__(self, time_window: int = 10):
"""Initialize your data structure here."""
pass
def should_accept_message(self, timestamp: int, message: str) -> bool:
"""Returns True if the message should be accepted, False otherwise."""
pass
Examples
Example 1
limiter = MessageLimiter(time_window=10)
limiter.should_accept_message(1, "foo") # Returns True (next allowed at >= 11)
limiter.should_accept_message(2, "bar") # Returns True (next allowed at >= 12)
limiter.should_accept_message(3, "foo") # Returns False (dropped; last accepted remains 1)
limiter.should_accept_message(8, "bar") # Returns False (dropped; last accepted remains 2)
limiter.should_accept_message(10, "foo") # Returns False (dropped; 10 = 1 + 10; next allowed at >= 21)
Constraints
1 <= time_window <= 10^60 <= timestamp <= 10^9- Timestamps in successive calls are strictly non-decreasing:
timestamp_{i} <= timestamp_{i+1}. 1 <= len(message) <= 50- At most
10^5calls will be made toshould_accept_message.
Edge Cases
- Multiple different messages arriving at the exact same timestamp.
- The same message arriving multiple times within the cooldown window (none of the dropped occurrences should extend the cooldown).
Hints
Hint 1
Use a hash map to track the next allowed timestamp or the last accepted timestamp for each unique message string.
Hint 2
When a message arrives, check if it exists in your map and whether the current timestamp is greater than or equal to the next allowed timestamp.
Hint 3
Make sure you only update the timestamp in your hash map when returning True; rejected calls must leave the previous timestamp untouched.
Follow-up questions
- How would you prevent memory from growing unbounded if millions of unique messages arrive over time?
- How would you make this implementation thread-safe under high-concurrency conditions?
- How would you adapt the system if incoming timestamps could arrive out of order due to network latency?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.