Debounce vs Throttle in JavaScript: What's the Difference and When to Use Each
Debounce vs throttle explained with plain-language definitions, working implementations, real use cases (search, scroll, resize) and the mistakes that trip people up in interviews.
Debounce vs Throttle in JavaScript
Debounce and throttle both limit how often a function runs, which is why they get confused. The difference is which calls they let through. Getting this right matters for real performance work — and "implement debounce" is one of the most common frontend coding prompts.
The one-line difference
- Debounce: run the function once the calls stop — after a quiet period of
waitms. Rapid calls keep resetting the timer. - Throttle: run the function at most once per interval, no matter how many calls arrive.
Analogy: debounce is an elevator that waits until people stop getting in before it moves; throttle is a turnstile that admits one person every N seconds.
Debounce: implementation
function debounce(fn, wait) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), wait);
};
}
Each call clears the pending timer and schedules a new one, so fn only fires after the calls go quiet for wait ms. Note it preserves this and arguments — a detail interviewers look for.
Use it for: search-as-you-type (wait until the user pauses), validating a field after typing stops, saving a draft, and resize handlers where only the final size matters.
Throttle: implementation
function throttle(fn, interval) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
};
}
This "leading-edge" throttle runs immediately, then ignores calls until interval has passed. Variants add a trailing call so the final event isn't dropped.
Use it for: scroll handlers, mousemove/drag, and anything firing continuously where you want steady, regular updates rather than one at the end.
Which one do I want?
- Only the final value matters, after activity stops → debounce (search input, autosave).
- You want regular updates during continuous activity → throttle (scroll position, drag, analytics sampling).
Common mistakes
- Forgetting to preserve
this/arguments(breaks methods and event handlers). - Using debounce for scroll — the UI feels frozen until scrolling stops.
- Using throttle for search — you fire mid-typing and waste requests.
- Not exposing a
cancel()for pending calls when a component unmounts (a real cleanup bug).
Where this shows up in interviews
"Implement debounce" (then "now add cancellation," "now add a leading option") is a classic closures-plus-timers question. It also appears inside larger machine-coding prompts like autocomplete, where you debounce the query, not the render. You can practise implementing and running both against real tests in the Mock Interview mode of Frontend Interview Prep.
Frequently asked questions
What's the core difference between debounce and throttle?
Debounce waits for a quiet period and then runs once; throttle runs at most once per interval regardless of how many calls arrive. Debounce cares about the end of activity; throttle caps the rate during activity.
When should I use debounce vs throttle?
Use debounce when only the final value matters after the user stops (search, autosave, resize). Use throttle when you want regular updates during continuous events (scroll, drag, mousemove).
Is "implement debounce" a common interview question?
Yes — it's a widely reported, commonly-discussed frontend prompt that tests closures, timers and preserving this/arguments. Practise it with real tests in Frontend Interview Prep, and review the JavaScript interview questions it connects to.
Implement debounce and run it against real tests, free.
Everything runs in your browser. Nothing leaves your device.
Open Frontend Interview PrepUnderstand the runtime behind it — read the guide.