czay.dev
Writing

What's the Difference Between Debounce and Throttle?

Typing "istanbul" into a search box sends 8 requests to the server. For 10,000 users, that means 80,000 requests. Debouncing drops this to 1, while throttling drops it to 4 — but they aren't the same thing, and using the right one matters.

Furkan ÖzaySeptember 15, 2026 · 2 min read
What's the Difference Between Debounce and Throttle?

You type "istanbul" into a search box. Eight letters, eight separate keyup events — and eight separate API requests fired. The user searched once, but you queried the server eight times.

The bill

Multiply that by ten thousand users: eighty thousand requests. Six out of seven of those are thrown in the trash before the response even arrives, because the user kept typing.

Debounce: wait for the last event

Debounce resets the timer every time it fires. If no new trigger arrives within the specified time (say, 300ms), it sends the final request just once.

JavaScript
function debounce(fn, delay = 300) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}
 
const search = debounce((query) => fetch(`/api/search?q=${query}`));

Eight keystrokes drop down to a single request once the user stops typing.

Throttle: emit at regular intervals

Throttle doesn't wait. It allows execution at most once within the specified interval (say, 300ms), swallowing any events that arrive in between.

JavaScript
function throttle(fn, interval = 300) {
  let last = 0;
  return (...args) => {
    const now = Date.now();
    if (now - last >= interval) {
      last = now;
      fn(...args);
    }
  };
}

Debounce cares about the last event; throttle cares about the regular interval.

Which one to use where

A simple rule of thumb so you don't mix them up: if you can wait for the final result, use debounce — search inputs, form validation, autosave. If you need to thin out an ongoing stream, use throttle — scroll listeners, window resizing, mouse movement.

Tip: Bonus: cancel the previous request

If you're using React, pair debounce with AbortController; abort the previous request whenever you trigger a new one. That way, even on a slow network, a stale response won't overwrite your latest query.

Wrapping up

You don't need a library for either; an eight-line function gets the job done. The key is simply knowing which one belongs where.