Is Node.js really single-threaded?
The answer - taking a page out of the senior engineer playbook - is, it depends.
Unless you explicitly write code that uses multiple threads (see
web-worker threads and
But this does not mean the entirety of Node.js works this way. Enter libuv, the async I/O library that is a part of Node.js. libuv maintains a pool of worker threads that are used by Node.js to perform long-running operations in the background, without blocking its main thread. Like disk I/O for example.
To quote from this excellent stack overflow answer,
Certain functions and modules, usually written in C/C++, support asynchronous I/O. When you call these functions and methods, they internally manage to pass the call on to a worker thread. For instance, when you use the fs module to request a file, the fs module passes that call on to a worker thread, and that worker waits for its response, which it then presents back to the event loop that has been churning on without it in the meantime.
So how does all of this work?
Consider a call to
fs.readdir that the event loop needs to pass on to a worker thread. The thread pool is used through submitting a work request to a queue. A work request here typically has a function that needs to be executed in a thread and a callback.
When at least one thread in the thread pool is idle, the first work request from the queue is assigned to that thread. If there are no free threads, the work request waits in the queue untill a thread frees up. Once the function running on the separate thread finishes, the callback from the work request is called with the results.
For a more in-depth explanation on why this matters and a good example using libuv, this article is worth reading.