Debouncing & Throttling
debt(d5/e3/b3/t5)
Closest to 'specialist tool catches' (d5). ESLint and Lighthouse (listed in detection_hints.tools) can identify raw event handlers without debounce/throttle and performance issues from excessive event firing, but these require specific rule configuration or performance auditing rather than default linting.
Closest to 'simple parameterised fix' (e3). The quick_fix indicates wrapping handlers in debounce/throttle calls, which is a straightforward pattern replacement. However, retrofitting across multiple event handlers may touch several files, keeping it at e3 rather than e1.
Closest to 'localised tax' (b3). Applies only to web contexts per applies_to, and the choice affects frontend event handling patterns. Once you establish the convention (debounce for input, throttle for scroll), it's a localised concern per component rather than a system-wide architectural commitment.
Closest to 'notable trap' (t5). The misconception field explicitly states developers believe 'debounce and throttle produce the same result with different syntax' when they solve fundamentally different problems. This is a documented gotcha that most frontend developers eventually learn through experience, but the confusion causes real bugs like throttling search input and getting stale queries.
Also Known As
TL;DR
Explanation
Debouncing delays an action until a quiet period has elapsed after the last trigger — a search-as-you-type field waits 300ms after the last keystroke before firing an API call. Throttling limits an action to at most once per time window regardless of trigger frequency. In PHP backends, throttling manifests as rate limiting (token bucket or sliding window via Redis). Debouncing is primarily a frontend concern but its server-side equivalent is request coalescing — combining multiple rapid identical API calls into one using a short-lived lock and cached result. Both patterns reduce unnecessary load on databases and external services.
Diagram
flowchart TD
subgraph Debounce
D_INPUT[User types rapidly] --> D_WAIT[Wait 300ms after last keystroke]
D_WAIT --> D_FIRE[Fire ONCE after typing stops]
D_USE[Use for: search autocomplete<br/>form validation]
end
subgraph Throttle
T_INPUT[100 scroll events per second] --> T_LIMIT[Allow max 1 per 100ms]
T_LIMIT --> T_FIRE[Fire at most 10 per second]
T_USE[Use for: scroll handlers<br/>API rate limiting]
end
style D_FIRE fill:#238636,color:#fff
style T_FIRE fill:#1f6feb,color:#fff
style D_USE fill:#d29922,color:#fff
style T_USE fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Confusing debounce (run after quiet period) with throttle (run at most every N ms) — they solve different problems.
- Throttling search input that needs the most recent value — debounce is correct; throttle may use a stale query.
- Not cancelling previous timers in a debounce implementation — multiple handlers fire instead of one.
- Applying debounce server-side for rate limiting — use throttle/rate limiting middleware instead.
Code Examples
// No debounce — search fires on every keystroke:
document.getElementById('search').addEventListener('input', (e) => {
fetch('/search?q=' + e.target.value); // 1 request per keystroke
});
// Debounced — fires 300ms after typing stops:
let timer;
document.getElementById('search').addEventListener('input', (e) => {
clearTimeout(timer);
timer = setTimeout(() => fetch('/search?q=' + e.target.value), 300);
});
// JavaScript — debounce (waits for activity to stop)
function debounce(fn, ms) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
const onSearch = debounce(async (q) => fetchResults(q), 300);
input.addEventListener('input', e => onSearch(e.target.value));
// Throttle (fires at most once per interval)
function throttle(fn, ms) {
let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= ms) { last = now; fn(...args); }
};
}
window.addEventListener('scroll', throttle(updateHeader, 100));
// PHP rate limit equivalent: Redis INCR + EXPIRE (see brute_force term)