Repository navigation
Deprecate process.nextTick in favor of queueMicrotask #36870
Description
Activity
- addedstreamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
on Jan 11, 2021 - addedlib / srcIssues and PRs involving general changes in the lib/ or src/ directories.Issues and PRs involving general changes in the lib/ or src/ directories.and removedstreamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
on Jan 11, 2021 As you suggest,
process.nextTick()is used far too extensively to be deprecated. The other issue is that the two methods (nextTick()andqueueMicrotask()) serve two entirely different goals at a purely technical level. They certainly appear similar and are probably interchangeable in most userland cases, there are situations where switching toqueueMicrotask()could be a performance loss and a breaking change in timing expectations (albeit unlikely). As an alternative to deprecation, we likely should document the differences between the two and give specific recommendations on when they should be used -- with deference given toqueueMicrotask()for most userland use cases. /cc @mcollinaReacted by Marcos BérgamoPR: #37484
The assessment @jasnell did is correct. I don't think we'll be able to remove process.nextTick(), it's everywhere.
- added a commit that references this issue
on Feb 23, 2021 Since it seems slower than nextTick. I'm not sure everyone agrees nextTick should be deprecated. We should though be more explicit about the edge cases with
nextTick.Does the "write idiomatic JavaScript, we will optimize" rule apply here? queueMicrotask being the idiomatic API.
Likely not without it being a significant breaking change. The fact that
queueMicrotask()tasks are scheduled in sequence with Promise then/catch/finally handlers would make it a pretty significant change in the timing contract.Consider the following examples:
const p = Promise.resolve(); p.then(() => { process.nextTick(() => console.log('a')); }) p.then(() => { queueMicrotask(() => console.log('b')); }) p.finally(() => { console.log('c'); });
The order in which the items are printed here is: c, b, a.
If you change the
process.nextTick()into a queueMicrotask...const p = Promise.resolve(); p.then(() => { queueMicrotask(() => console.log('a')); // process.nextTick(() => console.log('a')); }) p.then(() => { queueMicrotask(() => console.log('b')); }) p.finally(() => { console.log('c'); });
The order becomes c, a, b
While the change is extremely subtle on the surface, it can cause significant problems in practice, particularly with code that's been written to expect a particular timing.
That's not to say we shouldn't make that kind of change! It just means we have to be careful and understand that it could definitely break things.
Reacted by Robert Nagy and Said Akhmed Agitaev@jasnell The PR is pretty nice! Thank you for picking this up 😻
It does seem to me like @vweevers point is valid as in: use of queueMicrotask should over time should be same fast / faster. Very curious why it isnt.
In any case: I agree that a change of a current API does not make sense. But do new API's need to on the "nextTick" timing?
It's really not a matter of the performance difference between
queueMicrotask()andprocess.nextTick()... the two should have nearly identical performance profiles. The issue comes down specifically to the timing and order of execution. The sentiment in @vweevers comment is correct, however,queueMicrotask()has become the more idiomatic multi-platform approach and should be favored by the overwhelming majority of user code cases, withprocess.nextTick()falling solely in the realm of Node.js core and library authors.Reacted by Martin Heidegger- added a commit that references this issue
on Feb 28, 2021 - added a commit that references this issue
on May 1, 2021 - added a commit that references this issue
on May 22, 2026
Trying to work out some things with readable-stream recently and I noticed that
queueMicrotaskseems to be sharing the same operational paradigm asprocess.nextTick(as in: same time & style of execution). It is native to the v8 and available in browsers, has some async hooks available so I was wondering if - long term and in the spirit of cross-platform compatibility - to shift, little-by-little, fromprocess.nextTicktoqueueMicrotask? 😅The request to deprecate may be a bit much, as
process.nextTickis probably used everywhere and I was wondering if a soft-deprecation may be a good idea: i.e. mention thatqueueMicrotaskis the preferred way to go and that it only exists for legacy reasons? And maybe not use it for new API's?