Blog post

Debounce vs Throttle in JavaScript: The Art of Saying ‘Not Yet’ and ‘Not Too Often’

Priyanka Pakhale

-
June 18, 2025
Debounce
Throttle
Javascript
Performance Optimization

If you’ve ever typed into a search box and felt your browser gasp for air — you’ve met the chaos of uncontrolled events.

Your users scroll, type, resize windows, drag sliders — all of which can trigger hundreds of JavaScript events per second. Without control, your app becomes a frantic orchestra with no conductor. Performance drops, animations stutter, and the UX takes a hit.

That’s where debounce and throttle come in — not just as optimization techniques, but as tools of restraint.

Let’s demystify them, once and for all.

💥 The Chaos: Too Many Events, Too Fast

Imagine this:

  • A search input fires an API call on every keystroke
  • A window resize event recalculates layouts on every pixel shift
  • A scroll listener keeps hammering analytics as the user glides down a page

Enter: debouncing and throttling

⏳ Debounce: “Let’s Wait and See…”

Debounce waits until the storm calms down before doing anything

Debounce is perfect when you’re okay with acting after the user has finished interacting — like when they stop typing.

📦 Real-World Example: Search Box

function debounce ( fn, delay ) {
let timer;
return ( ...args ) => {
clearTimeout (timer);
timer = setTimeout ( () => fn. apply ( this , args), delay); }; }
const handleSearch = debounce ( () => {
console . log ( "Searching
for:" , e. target . value ); }, 300 );
input. addEventListener ( "input" , handleSearch);

Even if the user types “hello world”, handleSearch fires once, 300ms after the last keystroke.

🔍 Great for:

  • Autocomplete / search bars
  • Validating forms
  • Resizing the window and acting after the resize ends

🚀 See It in Action: Debounce vs No Debounce

In this side-by-side demo, both inputs receive the same keystrokes, but notice the difference in API calls triggered

Left (without debounce) : 11 queries for 11 keys
Right (with debounce) : Just 1 query after typing ends

👉 Try it on Codepen: Search without debounce | Search with debounce

🔂 Throttle: “I’ll Do It, But Not Too Often”

Throttle says: “I’ll run, but only once every X milliseconds — max”

Throttle is ideal when you want regular updates, but don’t want to overdo it.

📦 Real-World Example: Scroll Tracking

function throttle ( fn, limit ) {
let inThrottle;
return ( ...args ) => {
(!inThrottle) {
fn. apply ( this , args);
inThrottle = true ;
setTimeout ( () => inThrottle = false , limit); } }; }
const handleScroll = throttle ( () => {
console . log ( "Scroll event at" , new Date (). toISOString ()); }, 200 );
window . addEventListener ( "scroll" , handleScroll);

Even if the user scrolls like they’re chasing treasure, this function fires once every 200ms.

🧭 Great for:

  • Scroll position updates
  • Animation triggers
  • Polling every few seconds

🚀 See It in Action: Throttle vs No Throttle

In this scroll demo, both windows are scrolled the same way, but notice how throttling limits the number of events triggered, making the right one much calmer and more efficient

Left (without throttle) : 400+ events fired
Right (with throttle) : 7 events fired

👉 Try it on Codepen: Scroll without throttle | Scroll with throttle

⚖️ Debounce vs Throttle: When to Use What?

📚 Metaphor Time

⏳ Debounce is like waiting for someone to finish talking before you reply — no interruptions, just thoughtful timing. ⏱️ Throttle is like saying, “I’ll check in every 10 seconds — no matter how much you talk in between.”

🎭 Both are polite. Both are smart.
One listens for silence. The other runs on a schedule.

📌 Rule of Thumb

  • Use debounce when you care about the final result
  • Use throttle when you care about regular updates

🧰 Bonus: Lodash Makes Life Easier

Instead of reinventing the wheel every time, use Lodash which provides battle-tested _.debounce and _.throttle utilities.

import {
debounce, throttle }
from 'lodash' ;
const debouncedFn = debounce ( () => console . log ( 'Search!' ), 300 );
const throttledFn = throttle ( () => console . log ( 'Scroll!' ), 200 );

They’re well-tested, widely used, and battle-hardened for production.

🎯 Final Thoughts

In the world of frontend performance, small changes make a big difference.
Debounce and throttle aren’t just code tricks — they’re UX tools that help your app feel faster, smoother, and more intentional.

So the next time you’re debugging a laggy UI or thinking “why is this firing so many times?” — reach for one of these.

And remember:
Sometimes, the best feature is knowing when not to react.

🤝 Let’s Connect on LinkedIn

If this article helped you see debounce and throttle in a new light, I’d love to hear from you!
Feel free to connect with me on LinkedIn — whether you have questions, want to share your thoughts, or just enjoy chatting about clean, thoughtful frontend experiences. 🚀

Related Blog Posts