AO
Back

Notification Rate Limiter: User, Team and Company Limits

Phone ScreenPhone ScreenLast reported July 2026Low Frequency

Problem Overview

You're given
function company(url: string): string[];
function lookup(url: string): string[];
function company_id(url: string): string[];
Helper variants seen across reports. Don't implement HTTP fetching or HTML parsing — the helper handles both.
Full problem statement

The round: a Cursor coding screen (the second round in one report): write a notification rate limiter and run it on real test cases. Two reports, March and July 2026. In one, the interviewer runs real test cases and you write the code and verify it; the follow-up grows it into a rate limiter system design, and that candidate failed because time ran out before the design was complete. In the other, part 2 makes the limiter extensible.

The limits: both reports have the same three levels, user, team and company. One gives the numbers: a user may send at most 3 notifications in 10 minutes, a team at most 10, a company at most 20. The other says a helper is given that returns a user's team and company, and that when the call returns True the notification is counted.

Given here: a helper, lookup, takes a user id and returns (team_id, company_id); the constructor receives it. Timestamps are seconds and arrive in order; 10 minutes is 600 seconds, and a send counts against the window while it is less than 600 seconds old. The units and that boundary are ours, so ask; the tests stay clear of the exact boundary.

Part 1 — three-level limits: NotificationRateLimiter(lookup) with can_send_notification(user_id, timestamp). Return True and count the notification at the user, team and company levels if all three limits allow it; return False and count nothing if any level is full. One report names it should_send_notifications.

Part 2 — message_size and pluggable rules: ExtensibleRateLimiter(lookup) builds on Part 1. can_send_notification(user_id, timestamp, message_size=0) takes the new parameter, and register_handler(handler) adds a rule without changing the class. The interviewer gives example rules, such as "a user may send at most 4 messages of 50 length per minute"; the point is that a new rule never touches the core code. Here a handler is any object with two methods, allows (given req, returns True or False) and record (given req), where req is a dict with user_id, team_id, company_id, timestamp and message_size; that protocol is ours. A send goes through only if the three limits and every handler allow it, and only then is it counted and recorded by every handler.

Follow-up Arc

Interviewers escalate through these phases. The order varies, but most candidates see at least one from each bucket.
Distributed scale · 1Trade-off discussion · 2
Distributed scale

How would you turn this into a full distributed rate limiter system design?

Probes for: After pluggable design is discussed
Trade-off discussion

How would you extend this to support arbitrary new rules (e.g., 'user can send at most 4 messages of 50 chars per minute') without modifying the core code?

Probes for: After candidate implements the basic three-level deque solution

Walk me through real test cases and verify your implementation produces the correct output.

Probes for: During or after coding

Approach Trade-offs

Approaches actually attempted in reports — including ones that lost candidates time. Pick deliberately.
ApproachNotes
Fixed window counterSimpler to implement but less accurate at window boundaries; interviewers appear to expect a sliding window approach given the deque hint.
Token bucketWell-known rate limiting algorithm; supports burst traffic more naturally, but adds complexity and wasn't the approach mentioned by candidates who passed.

What Reports Emphasize

Common mistakes: Running out of time: one candidate failed because time ran out before the design extension was complete.

Interviewer hints: The interviewer explicitly described concrete new rule examples (e.g., 'user may send at most 4 messages of 50 characters per minute') to prompt the candidate to think about extensibility without modifying the core code.

What passers do: One candidate's approach: a deque per user, team and company, pruning expired timestamps before each check; then register_handler for the pluggable rules.

Why people fail: Ran out of time before completing the extension/system design portion; Could not produce a working, bug-free implementation that passed all test cases within the allotted time; Proposed a design for extensibility that still required modifying core rate limiter code to add new rules

Edge cases probed: Notifications at exactly the boundary of the 10-minute window (expiry edge); Multiple users in the same team hitting the team limit while individual user limits are not yet reached; Multiple teams in the same company hitting the company limit; A notification that should be rejected at the company level even though user and team limits are fine; Adding new rate limit rules without touching core code (extensibility boundary)

Practice

Write your own against 7 test cases, or read the worked solution — approach, complexity, and code that runs.
Cursor · Phone Screen · Reported 2× across candidate reports
Is this helpful?