Script Valley
Web Performance Fundamentals
JavaScript PerformanceLesson 4.4

What causes long tasks on the main thread and how to fix them

long tasks definition, 50ms threshold, main thread blocking, INP, setTimeout chunking, scheduler.postTask, Web Workers, requestAnimationFrame, isInputPending

Breaking Up Long Tasks

A long task is any main thread task that takes more than 50ms. During a long task the browser cannot respond to user input, causing jank and high INP scores.

Three strategies to break up long tasks:

1. setTimeout chunking — split a loop into chunks separated by a setTimeout(0) to give the browser breathing room:

function processInChunks(items, chunkSize = 100) {
  let index = 0;
  function processChunk() {
    const end = Math.min(index + chunkSize, items.length);
    for (; index < end; index++) {
      processItem(items[index]);
    }
    if (index < items.length) {
      setTimeout(processChunk, 0);
    }
  }
  setTimeout(processChunk, 0);
}

2. scheduler.yield() — the modern approach, yields specifically to input events:

for (let i = 0; i < items.length; i++) {
  processItem(items[i]);
  if (i % 50 === 0) await scheduler.yield();
}

3. Web Workers — move computation entirely off the main thread for CPU-intensive work (parsing, sorting, crypto, image processing):

// main.js
const worker = new Worker(new URL('./worker.js', import.meta.url));
worker.postMessage(largeDataset);
worker.onmessage = e => renderResults(e.data);

Identify long tasks in the Performance panel — they appear as red-flagged tasks. The Blocking Time row shows tasks that exceed 50ms; each is a candidate for chunking or offloading.

Up next

How to use a bundle analyzer to find and remove large dependencies

Sign in to track progress