Reference guide · performance · Published 2026-08-16 · 3 min read
Using requestIdleCallback for non-critical background work
requestIdleCallback scheduling of background work, idle budget, timeout, and alternatives compared.
- ·See how it runs
- ·Write an idle task
- ·Choose alternatives
requestIdleCallback schedules a function to run in a browser's idle periods, when the main thread is not busy with a user interaction or a paint. It is a tool for deferring low-priority background work so it does not delay the things the user cares about.
See how it runs
- It is a hint, not a deadline. The callback runs when the browser believes the main thread is idle. On a busy page it may never run promptly, so treat "idle" as available headroom rather than guaranteed execution time.
- It receives an
IdleDeadline. The callback gets an object with atimeRemaining()method that tells you how many milliseconds are left before the browser wants to render or respond to input. Return control when it reaches zero instead of forcing the task through. - A
timeoutoption forces execution. Passing{ timeout: 2000 }tells the browser to run the callback within 2 seconds even if idle time never comes, which protects the task from starving while still letting the browser fit it in when possible.
Write an idle task
A typical pattern runs a chunk and re-schedules if the deadline runs out:
function processQueue(deadline) {
while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && items.length > 0) {
const item = items.pop();
// do the low-priority work for item
}
if (items.length > 0) {
requestIdleCallback(processQueue, { timeout: 2000 });
} else {
done();
}
}
requestIdleCallback(processQueue, { timeout: 2000 });
- Keep work small and interruptible. Break large workloads into chunks you can stop between frames; otherwise you defeat the purpose.
- Do not mutate layout mid-idle. Reading or forcing layout inside an idle callback can still trigger a layout thrash that blocks rendering, so keep task work cheap.
- Watch for partial support. Some older browsers lack
requestIdleCallback; feature-detect it and fall back to running the work on a smallsetTimeoutso the feature still completes.
Choose alternatives
- Use
requestAnimationFramefor visual work. rAF aligns with the render loop and is right for animation and paint-affecting work, not general background logic. Assign work that must run each frame to rAF; assign work that can wait torequestIdleCallback. - Use Web Workers for heavy work. CPU-heavy processing that does not touch the DOM belongs in a dedicated thread (see Web Workers), where it cannot block the main thread at all.
- Measure the main-thread impact.
requestIdleCallbackreduces the risk a task delays input or a frame, but it does not shrink the total cost. Pair it with a check on long animation frames (see LoAF) to confirm the main thread is actually quiet.