The browser’s main thread is a limited resource
Managing Main Thread load through task splitting, yielding, event batching and moving computations into workers.

When we think about frontend optimization, bundle size, caching, network requests or reducing unnecessary rerenders usually come to mind. But on interactive screens (streaming chat, feeds, animations), the Main Thread itself often becomes the bottleneck.
The problem is that absolutely everything executes sequentially on the main thread: JS execution, event handling, DOM rendering, style calculations, Layout and Paint. If a function takes 200 ms, the browser literally “goes blind” for those 200 ms. It can’t draw a new frame or respond to a click.
The article identifies two fundamental approaches to managing main-thread load:
-
Divide time sensibly within the thread (Yielding & Scheduling)
When work inevitably has to run on the Main Thread, long tasks (Long Tasks > 50 ms) need to be split into time slices:
- Splitting & Yielding: Break large computations or rendering of many elements (for example, batches of WebSocket messages) into small chunks. Between chunks, yield through
requestAnimationFrameorscheduler.yield()so the browser has time to draw a frame and process user input. - Batching: Group frequent events (scrolling, text input, resize) through throttling/debouncing, or tie updates strictly to the redraw frame.
- Prioritizing & Deferring: Defer noncritical work (through
requestIdleCallbackorIntersectionObserver) and prioritize only what directly affects UI responsiveness.
- Splitting & Yielding: Break large computations or rendering of many elements (for example, batches of WebSocket messages) into small chunks. Between chunks, yield through
-
Move work off the Main Thread
The most effective optimization is to avoid loading the main thread at all:
- Compositor-only animations: Use only
transformandopacity. They are handled by a separate compositing thread and don’t trigger Layout/Paint recalculation. - The FLIP pattern: Calculate the complex math of changes before the animation, then animate only
transform. - Web Workers: Hand heavy data parsing, filtering or cryptography over to background threads.
- Compositor-only animations: Use only
Read the full breakdown with interactive demos
Do you calculate the frame budget (10 ms) and split long tasks, or are you still fighting to optimize the bundle?