JavaScript servers are typically single-threaded. A Node.js server (often using the Express framework) only uses one CPU core at a time. It can still handle many requests at once by using an async event loop. That just means whenever a request has to wait on I/O (like to a database), the server puts it on pause and does something else for a bit.

This might sound horribly inefficient, but it's not really. Node servers do just fine with the I/O workloads associated with most CRUD apps (where processing is offloaded to the database). You only start to run into trouble with this model when you need your server to do CPU-intensive work.
A benefit of having a single-threaded server is that you don't have to worry about synchronization issues that can arise from multiple threads accessing shared memory. The event loop takes care of this for you.
Here's a simple example of an asynchronous operation in TypeScript:
async function fetchUserData(userId: number): Promise<User> {
const res = await fetch(`https://api.example.com/user/${userId}`);
return res.json();
}
await for promises to resolve.Click to play video