# Concurrency

## libuv

**libuv** is a **C library** that powers Node.js’s async I/O. It handles **event loops, asynchronous operations, and thread pools**.

#### Responsibilities of libuv

* Implements the **event loop** (so Node.js itself doesn’t need to).
* Provides a **thread pool** (default = 4 threads, configurable via `UV_THREADPOOL_SIZE`).
* Wraps platform-specific features:
  * **Unix**: epoll, kqueue, etc.
  * **Windows**: IOCP (I/O Completion Ports).
* Handles async operations for:
  * File system (`fs` module)
  * DNS lookups
  * TCP/UDP sockets
  * Child processes
  * Timers

## Single Threaded

Node single threaded execution comes from its roots and engine used.

JavaScript was originally designed for browsers, where single-threaded execution (with an **event loop**) was the simplest way to manage UI updates and user interactions.

Node.js extends JavaScript to the server but keeps its **single-threaded event loop**. This design avoids **thread-safety issues** (like race conditions, deadlocks) since everything executes in a single main thread.

### Async IO

Instead of blocking threads for I/O operations (file reads, DB queries, network calls), Node.js uses **libuv** underneath, which delegates heavy I/O to the OS.

The **event loop** waits for these operations to finish and then invokes the registered callbacks.

That’s why Node.js can handle **tens of thousands of concurrent requests** on a single thread.

### Absctracted multi threading

Even though **your JavaScript code runs in one main thread**, Node.js internally can use **multiple threads** for I/O and background tasks. Example:

* File system operations (`fs` module)
* DNS lookups
* Crypto operations

These get pushed to **libuv’s thread pool** (default size = 4, configurable). So Node.js *does* use threads, but it abstracts them away.

## True Parallelism (Multitasking)

If you need **CPU-bound parallelism** (e.g., image processing, data crunching, encryption), async I/O alone isn’t enough. Node.js provides two main tools:

### Worker Threads (since Node.js v10.5.0, stable in v12)

Lets you run multiple threads, each with its own V8 instance.

Perfect for CPU-intensive tasks that would otherwise block the event loop.

{% hint style="info" %}
Here, the worker runs the loop **in a separate thread**, freeing the main thread.
{% endhint %}

```javascript
// worker.js
import { parentPort } from 'worker_threads';

let sum = 0;
for (let i = 0; i < 1e9; i++) {
  sum += i;
}

parentPort.postMessage(sum);
```

```javascript
// main.js
import { Worker } from 'worker_threads';
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';

// __dirname replacement in ESM
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

console.log('Main thread starting...');

const worker = new Worker(resolve(__dirname, 'worker.js'));

worker.on('message', (result) => {
  console.log('Result from worker:', result);
});

worker.on('error', (err) => console.error('Worker error:', err));
worker.on('exit', (code) => console.log('Worker exited with code:', code));

console.log('Main thread is free to handle other tasks.');
```

### Cluster Module

Spins up multiple Node.js processes (not threads) that share the same server port.

Useful for scaling across **multi-core CPUs**.

Load balancing is handled by the master process.

{% hint style="info" %}
Each worker is a **separate process** (more memory overhead than threads). Best for handling **many requests** in parallel.
{% endhint %}

```javascript
// cluster-app.js
import cluster from 'cluster';
import http from 'http';
import os from 'os';

const numCPUs = os.cpus().length;

if (cluster.isPrimary) {
  console.log(`Master process ${process.pid} is running`);

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork();
  });
} else {
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end(`Hello from worker ${process.pid}\n`);
  }).listen(3000);

  console.log(`Worker ${process.pid} started`);
}
```
