mediumBackend EngineerTechnology
What is the difference between process.nextTick() and setImmediate() in Node.js, and when would you use each?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
Interviewer asked:
> "We have code that needs to run 'as soon as possible but not synchronously.' Should we use process.nextTick() or setImmediate()? What's the difference, and what are the production implications?"
> "We have code that needs to run 'as soon as possible but not synchronously.' Should we use process.nextTick() or setImmediate()? What's the difference, and what are the production implications?"
Suggested Solution
Execution Order
console.log('1 - sync');
process.nextTick(() => console.log('2 - nextTick'));
Promise.resolve().then(() => console.log('3 - promise microtask'));
setImmediate(() => console.log('4 - immediate'));
setTimeout(() => console.log('5 - timeout'), 0);
// Output: 1, 2, 3, 4/5 (4 and 5 order varies on first event loop cycle)
// On subsequent cycles: always 4 before 5
Where They Run in the Event Loop
┌───────────────────────────────────┐
│ Event Loop Phases (in order): │
│ │
│ 1. Timers (setTimeout/setInterval) │
│ 2. Pending callbacks │
│ 3. Idle, prepare │
│ 4. Poll (I/O) │
│ 5. Check (setImmediate) ◄── HERE │
│ 6. Close callbacks │
│ │
│ BEFORE each phase: │
│ → process.nextTick queue ◄── HERE│
│ → Microtask queue (Promises) │
└───────────────────────────────────┘
Key Differences
process.nextTick()setImmediate()nextTickQueuecheckQueueThe Starvation Problem
// ❌ This will STARVE the event loop — I/O never gets processed
function recursiveNextTick() {
process.nextTick(recursiveNextTick);
}
recursiveNextTick();
// Other callbacks NEVER run!
// ✅ setImmediate allows I/O to process between iterations
function recursiveImmediate() {
setImmediate(recursiveImmediate);
}
recursiveImmediate();
// Other callbacks CAN run between iterations
When to Use Each
process.nextTick()
function EventEmitter() {process.nextTick(() => this.emit('ready'));
}
setImmediate()
async function batchProcess(items) {processItem(items[i]);
if (i % 100 === 0) {
await new Promise(r => setImmediate(r)); // Yield to I/O
}
}
}
Rule: Prefer
setImmediate() in production unless you specifically need pre-phase execution.