Answer is no - one thread can serve many clients.
TLDR; It's because Node.js is using asynchronous I/O
Under the hood Node.js uses two technologies - libuv and v8
- v8 is Javascript engine used by Google Chrome and other browsers (not interesting for us now).
- libuv is a library that provides the event loop and asynchronous I/O capabilities
What is the event loop?
Generally speaking it's a loop that's polling or querying some (usually external) source of events and a callback for each event that is executed when event is received. Something like this:
while (running) {
event = get_event();
callback = get_callback(event)
callback();
}
If we do fs.read()
, socket.write()
, setTimeout()
...
Under the hood this is going to 'schedule' events with callbacks that are about to be completed (using the callbacks) in future - but the code is not going to wait for each individual one, instead only the first event will be waited for (no matter which one completes first).
So get_event
will return first event that completes.
What is asynchronous I/O?
For example reading from a file is usually so called blocking operation - meaning we ask x bytes from a file and we are going to block execution until OS to gives us the bytes. This is synchronous I/O.
Using asynchronous I/O it's possible to ask OS to give us the bytes and not block so we can do something else. When the bytes are ready we will get notified by event loop and process them - so called non-blocking operation.
Node is doing exactly that - it's using mostly non-blocking operations to achieve concurrency on a single thread. Manipulating files and using network can be done using OS's asynchronous I/O.
It's extremely useful because I/O operations usually make majority of execution time so our code instead of waiting is doing something useful - like handling connection from 8th or 100th client.