- Interview Questions
- /
- Problems
- /
- Logger Rate Limiter
Logger Rate Limiter
Build a logger that lets each distinct message through at most once every 10 seconds. A small design question about remembering just enough state per key. Solve it below in Python or JavaScript, then read the walkthrough.
Problem
Design a class Logger that receives a stream of log messages, each tagged with a timestamp in seconds, and decides whether each one should actually be printed.
A message may be printed only if the same message text has not been printed in the last 10 seconds. More precisely, if a message is printed at time t, any identical message arriving before time t + 10 is suppressed, and one arriving at t + 10 or later is printed again. Suppressed messages do not reset the clock.
Implement:
Logger()creates a logger with no history.shouldPrintMessage(timestamp, message)returnstrueif the message should be printed attimestamp, otherwisefalse.
Calls arrive in non-decreasing timestamp order, and several messages can share the same timestamp.
In the tests, each case is a list of operations and their arguments. The first operation constructs the logger, and the expected output lists what each call returns (null for the constructor).
Example 1
- Input
- ["Logger", "shouldPrintMessage", "shouldPrintMessage", "shouldPrintMessage", "shouldPrintMessage"] [[], [0, "disk full"], [4, "disk full"], [5, "cpu hot"], [10, "disk full"]]
- Output
- [null, true, false, true, true]
"disk full" is printed at 0, so it is blocked until 10. At 4 it is suppressed. "cpu hot" is new. At 10 the window for "disk full" has passed.
Example 2
- Input
- ["Logger", "shouldPrintMessage", "shouldPrintMessage", "shouldPrintMessage"] [[], [3, "ping"], [8, "ping"], [12, "ping"]]
- Output
- [null, true, false, false]
The suppressed call at 8 does not restart the window. The window from time 3 lasts until 13, so 12 is still blocked.
Example 3
- Input
- ["Logger", "shouldPrintMessage", "shouldPrintMessage", "shouldPrintMessage"] [[], [7, "a"], [7, "b"], [7, "a"]]
- Output
- [null, true, true, false]
Different messages are tracked separately, even at the same timestamp.
Constraints
- 0 ≤ timestamp ≤ 10⁹
- Timestamps are passed in non-decreasing order.
- 1 ≤ message.length ≤ 30, lowercase letters, digits and spaces
- At most 10⁴ calls to shouldPrintMessage.
Practice
Runs 12 tests in your browser. Python loads on the first run (about 6 MB, then cached). Press ⌘/Ctrl + Enter to run.
Get asked Logger Rate Limiter in a real interview?
Interview Solver gives you a working solution live, during your actual coding interview. Invisible to screensharing.
How to solve Logger Rate Limiter
Pattern: Hash map of next allowed time
The only thing you need to know about a message is when it is next allowed to print. Older history doesn't matter: once a message prints at time t, everything before t is irrelevant for that message.
So keep a map from message text to the earliest timestamp it may print again. On each call, look up the message. If the current time has reached that value (or the message is new), print it and store timestamp + 10. Otherwise return false and leave the map alone, because a suppressed message must not push its own window forward.
Approach 1: Keep a list of every printed message
Append each printed (timestamp, message) to a list and, on each call, scan backward for the same message within the last 10 seconds. Correct, but each call can scan the whole history.
Time O(n) per call · Space O(n)
Approach 2: Queue plus set of recent messages
Keep a queue of printed messages from the last 10 seconds and a set of their texts. On each call, pop entries older than timestamp - 10 from the front and remove them from the set, then check the set. Memory stays bounded by the traffic in a 10 second window, which matters for long-running services.
Time O(1) amortized · Space O(m), m = messages in the last 10 seconds
Approach 3: Hash map of next allowed time
Store nextAllowed[message].
- If the message is missing or
timestamp >= nextAllowed[message], setnextAllowed[message] = timestamp + 10and returntrue. - Otherwise return
falsewithout touching the map.
Time O(1) per call · Space O(k), k = distinct messages
| Approach | Time | Space |
|---|---|---|
| Keep a list of every printed message | O(n) per call | O(n) |
| Queue plus set of recent messages | O(1) amortized | O(m), m = messages in the last 10 seconds |
| Hash map of next allowed time | O(1) per call | O(k), k = distinct messages |
Solution code
Try the practice editor first. Both solutions pass every test above.
Logger Rate Limiter solution in Python
class Logger:
def __init__(self):
self.next_allowed = {} # message -> earliest time it may print again
def should_print_message(self, timestamp: int, message: str) -> bool:
if timestamp < self.next_allowed.get(message, timestamp):
return False
self.next_allowed[message] = timestamp + 10
return TrueLogger Rate Limiter solution in JavaScript
class Logger {
constructor() {
this.nextAllowed = new Map(); // message -> earliest time it may print again
}
shouldPrintMessage(timestamp, message) {
if (this.nextAllowed.has(message) && timestamp < this.nextAllowed.get(message)) {
return false;
}
this.nextAllowed.set(message, timestamp + 10);
return true;
}
}Common mistakes
- Updating the stored time on a suppressed call. That keeps a chatty message blocked forever instead of letting it through every 10 seconds.
- Using `>` instead of `>=` at the boundary. A message printed at 0 may print again at exactly 10.
- Storing the last printed time but then comparing `timestamp - last > 10`, which is off by one at the boundary.
- Using a falsy check like `if (!map[msg])` when the stored value can be 0, which treats a real entry as missing.
What interviewers look for
Clarify the boundary first: "if it printed at 0, can it print at 10?" Then clarify whether suppressed messages extend the window. Interviewers often leave both ambiguous on purpose to see if you ask.
After the map solution, expect a question about memory: the map grows with every distinct message ever seen. Offer the queue-plus-set version or periodic cleanup of entries whose next allowed time has passed, and mention that a real service would also need thread safety.
Follow-up questions
The map keeps every message forever. How do you bound memory?
Keep a queue of (time, message) for printed messages and evict entries older than 10 seconds on each call, deleting them from the map too. Memory then depends only on how many distinct messages printed in the last window.
What if many threads call shouldPrintMessage at once?
The check and the update must be atomic, or two threads can both see "allowed" and print. Use a lock around the read-modify-write, or a concurrent map with a compare-and-set on the stored time. Striping locks by message hash reduces contention.
What if the limit were "at most N prints per message per 10 seconds"?
Store a small queue of recent print times per message. On each call drop times older than `timestamp - 10`; print only if fewer than N remain, then append the new time. That is a per-key sliding window log.
Companies that ask Logger Rate Limiter
Logger Rate Limiter is tagged by 101 companies in our interview dataset. The score shows how often it comes up at each company.
- Vinted100%
- Verily100%
- Appfolio100%
- Nec97%
- Zuora96%
- Endava92%
- Buffer91%
- Global Relay91%
- Discovery90%
- Softserve89%
- Clear88%
- Olympus86%
- Netflix85.5%
- Fujitsu84%
- Waymo83.6%
- S P Global83%
- Bairesdev82%
- Verisk80%
- Aptiv80%
- Airtable80%
- Exl79%
- Palo Alto Networks78.7%
- Reddit78.1%
- Activtrak76%
and 77 more.
Practice next
Get live help in the real interview
Working solutions in real time during your actual interview. Invisible to screensharing.
Start Free TrialNo credit card required