Node.js Timers

Node.js timers let you schedule code to run later, repeatedly, or as soon as the current operation completes, all without blocking the rest of your program.

What Are Timers in Node.js?

Timers are global functions - you don't need to require any module to use them - that schedule a callback to run at some point in the future via the event loop. Because Node.js is single-threaded and non-blocking, a timer never pauses your program; it simply tells the event loop "run this function later" and execution continues immediately with whatever code comes next.

  • setTimeout(fn, delay) - runs fn once, after at least delay milliseconds.
  • setInterval(fn, delay) - runs fn repeatedly, approximately every delay milliseconds, until stopped.
  • setImmediate(fn) - runs fn once, immediately after the current poll phase of the event loop completes.
  • clearTimeout(id) / clearInterval(id) - cancels a previously scheduled timer using the ID it returned.

setTimeout: Delayed Execution

setTimeout() schedules a callback to run once after a minimum delay. The delay is a floor, not a guarantee - if the event loop is busy running other code when the timer fires, the callback will be delayed further until the loop is free.

Example 1: Basic setTimeout usage

console.log('Start');

setTimeout(() => {
  console.log('This runs after ~2 seconds');
}, 2000);

console.log('End'); // logs immediately, before the timeout callback

setInterval: Repeated Execution

setInterval() behaves like setTimeout() but keeps firing every delay milliseconds until you explicitly stop it with clearInterval(). Forgetting to clear an interval is a common source of memory leaks and runaway background work in long-running Node.js processes.

Example 2: Counting with setInterval and stopping it

let count = 0;

const intervalId = setInterval(() => {
  count++;
  console.log(`Tick ${count}`);

  if (count === 3) {
    clearInterval(intervalId);
    console.log('Interval stopped');
  }
}, 1000);

setImmediate vs setTimeout(fn, 0)

setImmediate() is designed to run a callback as soon as possible after the current I/O event completes, and it is a separate phase of the event loop from timers. Inside the main module, the ordering between setTimeout(fn, 0) and setImmediate() is not guaranteed, but inside an I/O callback, setImmediate() always fires before a setTimeout(fn, 0) scheduled at the same point.

Example 3: Comparing setTimeout and setImmediate ordering

setTimeout(() => console.log('setTimeout callback'), 0);
setImmediate(() => console.log('setImmediate callback'));

console.log('Synchronous code runs first');

// Output order:
// Synchronous code runs first
// (then either setTimeout or setImmediate callback, order varies here)
FunctionTimingTypical Use
setTimeout(fn, 0)Runs on the next timers phaseDeferring work by at least one event loop tick
setImmediate(fn)Runs after the current poll phaseRunning code right after I/O, before further timers
process.nextTick(fn)Runs before the event loop continues at allDeferring work to the very end of the current operation
Note: It's always safe to call clearTimeout() or clearInterval() with an ID even if that timer has already fired or was never valid - Node.js simply does nothing in that case, so you rarely need to guard the call.
Note: If a setInterval() callback takes longer to run than the interval itself, calls can pile up and cause unpredictable behavior under load. For work of variable duration, prefer a recursive setTimeout() pattern that schedules the next run only after the current one finishes.

Exercise: Node.js Timers

When does the callback in setTimeout(fn, 0) actually execute?