AceDevHub
Modern PatternsFree

Debounce and Throttle

Control how often expensive functions run — search inputs, scroll handlers, and resize listeners — without melting the main thread.

IntermediateFreePerformance

Input and scroll events fire far faster than network or layout can afford. Firing fetch on every keypress DDOSes your own API; running layout reads on every scroll frame janks the UI. Debounce and throttle are timing strategies implemented with closures and setTimeout — interview favorites because they test both event loop understanding and practical product engineering.

Debounce — wait until activity pauses

Debounce delays execution until the caller stops invoking for N milliseconds. Each new call resets the timer. Perfect for search-as-you-type: send the query 300ms after the user stops typing, not on every keystroke. Also used for window resize end detection and auto-save drafts.

debounce.js
Loading editor…
Outputconsole
API search: jav calls: 1

Throttle — at most once per interval

Throttle guarantees the function runs at most once every N ms while events keep coming. Use for scroll position updates, mousemove tracking, and infinite scroll load-more triggers. Leading throttle runs immediately then ignores; trailing throttle runs after the window — pick based on UX.

throttle.js
Loading editor…
PatternBehaviorTypical use
DebounceRun after pauseSearch input, resize end
ThrottleRun on intervalScroll, mousemove, rate limits
requestAnimationFrameSync to paintVisual DOM updates

Debounce and throttle are not browser-only — rate-limit API polling, log batching, and queue flush timers use the same closure patterns. The implementation here is interview-sized; production code may add maxWait, cancel on unmount, and leading-edge options. Understand the mental model first, then reach for lodash.debounce when edge cases multiply.

Measure before optimizing: DevTools Performance panel shows whether scroll handlers or search inputs actually bottleneck your app. Applying throttle to every mousemove without evidence adds complexity. Debounce search at 250–400ms is a sensible default for internal admin tools; public SEO pages may prefer instant local filter with debounced analytics only.

Cancel and flush on unmount

UI components must clear debounce timers on unmount — otherwise setState on unmounted components triggers React warnings. Expose debounced.cancel() and debounced.flush() in library implementations so route changes immediately persist pending search queries when product requires it.

  • Debounce: wait for pause — search, resize end, auto-save
  • Throttle: cap frequency — scroll, mousemove, sendBeacon batching
  • requestAnimationFrame: sync visual reads/writes to paint — not interchangeable with throttle


  1. 1Debounce: wait for quiet period — search boxes
  2. 2Throttle: cap frequency — scroll handlers
  3. 3Both use closures to remember timer state
  4. 4Clean up timers on component unmount in UI code
  5. 5Next lesson: structuredClone and immutability