Bottlenecks in JS code
1. Main Thread Blocking
JS is single-threaded. Any heavy operation blocks the UI, rendering, and event handling.
Examples:
- large loops (
for,while,forEach) withoutsetTimeout/requestIdleCallback; - parsing or processing large JSON (
JSON.parse(hugeData)); - computationally heavy algorithms (sorting, recursion, encryption);
- synchronous requests (
XMLHttpRequestwithout async); - large DOM changes within a single frame.
How to fix it:
- split the work into chunks (
setTimeout,requestAnimationFrame); - use Web Workers for background computation;
- apply debounce / throttle for events.
2. Excessive re-renders and DOM manipulation
DOM operations are the most expensive in terms of performance.
Problems:
- too many element insertions/removals;
- recalculating styles and layout on every change;
- accessing
offsetHeight,getComputedStyle,scrollTop→ triggers reflow; - loops that modify the DOM.
How to fix it:
- use DocumentFragment, a virtual DOM, batch updates;
- cache element references;
- minimize
reflow- change a class for a whole group of elements at once; - in React: memoization, PureComponent, React.memo, useMemo, useCallback.
3. Excessive memory consumption (memory leaks)
Memory leaks cause the tab to get "heavier" over time, and the UI freezes.
Causes:
- uncleared timers (
setInterval,setTimeout); - "dangling" event listeners (not removed when the element is removed);
- closures that keep references to large objects;
- global variables (never cleared);
- caches that are never cleared.
Solutions:
- clear timers (
clearInterval,clearTimeout); - remove handlers (
removeEventListener); - use WeakMap / WeakSet;
- analyze with Chrome DevTools → Memory.
4. Inefficient loops and collections
Especially with large arrays.
Typical mistakes:
- nested
O(n²)loops with no real need; - using
.map()/.filter()/.reduce()on large arrays without optimization; - creating new arrays/objects on every iteration;
- frequent calls to
Array.splice()/Array.shift()(expensive operations).
What to do:
- use more suitable structures:
Set,Map,WeakMap; - use iterators, generators, for...of instead of
forEachfor large volumes; - profile sections with
performance.now().
5. Excessive network requests
Even fast JS code will not save you if the network is congested.
Problems:
- repeated requests without caching;
- duplicate API calls on every render;
- loading huge JS/CSS bundles;
- no gzip / brotli compression;
- no
lazy loading.
How to fix it:
- caching (HTTP cache, IndexedDB, SW, memoization);
- batching requests;
React Query,SWR,Cache-Control;- code splitting and dynamic import (
import()).
6. Poor rendering optimization (rendering bottlenecks)
The UI "jitters", animations lag, FPS drops.
Causes:
- too frequent changes to
style/transform; - using heavy shadows, filters,
border-radius; - not using the GPU (CSS animations without
transform: translateZ(0)); - recalculating layout on every animation frame.
Solutions:
- offload animations to the GPU;
- batch DOM changes into a single frame;
- use
will-change,transform,opacity; requestAnimationFrameinstead of timers for animations.
7. A heavy bundle (bundle size)
The more JS there is, the longer it takes to load and parse.
Causes:
- pulling in unnecessary libraries;
- duplicated dependencies;
- not using tree-shaking;
- inline JSON, large icons, images embedded in the code.
Solutions:
- analyze the bundle (
webpack-bundle-analyzer,next build --analyze); - tree-shaking, code splitting, dynamic import();
- use a CDN, HTTP/2, ESM bundles;
- minification (Terser, SWC).
8. Suboptimal data structures and algorithms
Example: sorting an array of 100,000 elements with
sort()without a comparator, or searching withfilter()instead of aSet.
What to do:
- choose the structure for the task:
Setfor uniqueness,Mapfor fast lookups; - avoid a linear search when a hash-based lookup can be used;
- use binary search, cache computed values.
9. Lack of profiling and metrics
The most common mistake is "optimizing at random".
Solutions:
- Chrome DevTools (Performance, Memory, Coverage);
console.time(),performance.mark()/measure();- Lighthouse / Web Vitals;
- Sentry Performance, New Relic, Datadog.
Quick summary
| Category | Example problem | How to fix it |
|---|---|---|
| Thread blocking | A long loop | Split it up, use a Worker |
| DOM | Lots of reflow | Batch updates |
| Memory | Leaks | WeakMap, cleanup |
| Loops | O(n²) | Optimize |
| Network | Repeated requests | Cache them |
| Rendering | FPS < 60 | GPU animations |
| Bundle | 2 MB of JS | Tree-shaking |
| Algorithms | Wrong structure | Choose based on the task |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.