Skip to main content

Throttle - Solution & Explanation

MediumPremiumFree on FleetCode5 min read
Practice this problem

Problem Statement

Given a function fn and a time in milliseconds t, return a throttled version of that function.

A throttled function is first called without delay and then, for a time interval of t milliseconds, can't be executed but should store the latest function arguments provided to call fn with them after the end of the delay.

For instance, t = 50ms, and the function was called at 30ms, 40ms, and 60ms.

At 30ms, without delay, the throttled function fn should be called with the arguments, and calling the throttled function fn should be blocked for the following t milliseconds.

At 40ms, the function should just save arguments.

At 60ms, arguments should overwrite currently stored arguments from the second call because the second and third calls are made before 80ms. Once the delay has passed, the throttled function fn should be called with the latest arguments provided during the delay period, and it should also create another delay period of 80ms + t.

Throttle DiagramThe above diagram shows how throttle will transform events. Each rectangle represents 100ms and the throttle time is 400ms. Each color represents a different set of inputs.

 

Example 1:

Input: 
t = 100, 
calls = [
  {"t":20,"inputs":[1]}
]
Output: [{"t":20,"inputs":[1]}]
Explanation: The 1st call is always called without delay

Example 2:

Input: 
t = 50, 
calls = [
  {"t":50,"inputs":[1]},
  {"t":75,"inputs":[2]}
]
Output: [{"t":50,"inputs":[1]},{"t":100,"inputs":[2]}]
Explanation: 
The 1st is called a function with arguments (1) without delay.
The 2nd is called at 75ms, within the delay period because 50ms + 50ms = 100ms, so the next call can be reached at 100ms. Therefore, we save arguments from the 2nd call to use them at the callback of the 1st call.

Example 3:

Input: 
t = 70, 
calls = [
  {"t":50,"inputs":[1]},
  {"t":75,"inputs":[2]},
  {"t":90,"inputs":[8]},
  {"t": 140, "inputs":[5,7]},
  {"t": 300, "inputs": [9,4]}
]
Output: [{"t":50,"inputs":[1]},{"t":120,"inputs":[8]},{"t":190,"inputs":[5,7]},{"t":300,"inputs":[9,4]}]
Explanation: 
The 1st is called a function with arguments (1) without delay.
The 2nd is called at 75ms within the delay period because 50ms + 70ms = 120ms, so it should only save arguments. 
The 3rd is also called within the delay period, and because we need just the latest function arguments, we overwrite previous ones. After the delay period, we do a callback at 120ms with saved arguments. That callback makes another delay period of 120ms + 70ms = 190ms so that the next function can be called at 190ms.
The 4th is called at 140ms in the delay period, so it should be called as a callback at 190ms. That will create another delay period of 190ms + 70ms = 260ms.
The 5th is called at 300ms, but it is after 260ms, so it should be called immediately and should create another delay period of 300ms + 70ms = 370ms.

 

Constraints:

  • 0 <= t <= 1000
  • 1 <= calls.length <= 10
  • 0 <= calls[i].t <= 1000
  • 0 <= calls[i].inputs[j], calls[i].inputs.length <= 10

Approach Overview

Problem Overview: You need to implement a throttle(fn, t) utility. The returned function can be called many times, but fn must execute at most once every t milliseconds. Calls made during the cooldown period should not trigger immediate execution, but the most recent call should run once the throttle window finishes.

Approach 1: Timestamp + Timer Throttling (O(1) time, O(1) space)

The efficient design keeps two pieces of state inside a JavaScript closure: the timestamp of the last execution and a pending timer. When the throttled function is called, compute the remaining cooldown using t - (now - lastExecution). If the remaining time is ≤ 0, execute the function immediately and update the timestamp. If the function is still in the throttle window, store the latest arguments and schedule a timer to run after the remaining delay.

The key insight is that only the latest call during the cooldown matters. Earlier calls inside the window are overwritten by the most recent arguments. When the timer fires, the stored arguments are passed to fn and the execution timestamp is updated. This produces the standard throttle behavior: one immediate call followed by at most one trailing call per interval.

This solution relies on closures and timers from the JavaScript runtime. The closure preserves internal state across invocations without exposing it globally. Every invocation performs only constant-time operations: timestamp calculation, optional timer scheduling, and argument storage.

Approach 2: Queue-Based Scheduling (O(1) amortized time, O(k) space)

Another way to reason about throttling is to push calls into a small queue and process them at fixed intervals using a repeating timer. Each incoming call adds its arguments to the queue, replacing the previous entry so that only the newest invocation remains pending. A periodic timer executes the queued call if one exists.

This model is conceptually simpler for understanding rate limiting and scheduling problems. However, it introduces slightly more state management and requires maintaining an interval lifecycle. In practice, most production implementations prefer the timestamp + timeout strategy because it avoids a constantly running timer and executes only when needed.

Recommended for interviews: The timestamp + timeout implementation is the expected solution. It demonstrates understanding of closures, timer scheduling, and event-loop behavior in JavaScript. Interviewers want to see that you track the last execution time and correctly schedule a trailing call with the latest arguments. Explaining why only the latest call inside the window should run shows solid understanding of design patterns used in real-world throttling utilities.

Solution

Code

TypeScript

Try this approach in the editor →

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Timestamp + Timeout ThrottleO(1) per callO(1)Preferred implementation for JavaScript throttling utilities and interviews
Queue-Based Interval ProcessingO(1) amortizedO(k)Useful when modeling throttling as a scheduled task processor

Video Solution

Throttle - Leetcode 2676 - JavaScript 30-Day Challenge • NeetCodeIO • 7,160 views views

Watch 4 more video solutions →

Frequently Asked Questions

Is Throttle easy or hard?
Throttle is rated Medium because the logic involves asynchronous timing and careful state management. The algorithm itself is simple, but handling edge cases such as trailing calls and argument updates requires a clear understanding of how timers interact with function calls.
Throttle Python/Java solution
The original problem targets JavaScript because throttling depends on timers such as setTimeout and closure behavior. Similar concepts can be implemented in Python or Java using scheduled executors or timers, but the LeetCode problem specifically expects a JavaScript or TypeScript implementation.
How to solve Throttle in O(1)?
Store the timestamp of the last execution and a reference to a pending timeout. When the function is called, compute the remaining cooldown. Execute immediately if the cooldown expired; otherwise schedule a timeout that runs the function with the latest arguments after the remaining time. This keeps every call O(1).
What is the best approach for Throttle?
The standard solution uses a timestamp and a timeout stored inside a closure. Each call checks how much time remains in the throttle window. If the window expired, the function executes immediately; otherwise a timer schedules the latest call to run after the remaining delay. This approach runs in O(1) time per invocation and uses constant space.
Is Throttle asked at Google/Amazon/Meta?
Throttle-style problems appear in frontend and JavaScript-focused interviews at companies like Meta, Amazon, and Google. Interviewers use them to test understanding of closures, timers, and event-loop behavior rather than heavy algorithms.
What data structure is used in Throttle?
The implementation mainly relies on a JavaScript closure to persist state across calls. Inside the closure you typically store a timestamp, a timeout reference, and the latest arguments. No complex data structures are required.
What is the time complexity of Throttle?
Each invocation of the throttled function performs a constant number of operations: reading the current time, calculating remaining delay, and optionally setting a timeout. Because of this, the time complexity is O(1) per call and the space complexity is O(1).

Ready to solve this problem?

Practice Throttle with our built-in code editor and test cases.

Practice on FleetCode