Suggest an editImprove this articleRefine the answer for “What is Node.js and how does it work?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Node.js** is a JavaScript runtime built on Chrome's V8 engine that runs JavaScript outside the browser. libuv handles async I/O on a thread pool, so the single JS thread never blocks on file reads or network calls. ```js const http = require('http'); http.createServer((req, res) => res.end('Hello')).listen(3000); ``` **Key:** one JS thread + non-blocking I/O = thousands of concurrent connections without spawning extra threads.Shown above the full answer for quick recall.Answer (EN)Image**Node.js** - a JavaScript runtime that executes JS code outside the browser, on the server. ## Theory ### TL;DR - Node.js is not a framework or a language - it's a runtime environment for JavaScript - Built on V8 (Chrome's JS engine) + libuv (a C++ async I/O library) - Single JS thread + non-blocking I/O: your code never waits idle for file reads or network calls - Great for I/O-heavy work (APIs, real-time apps, streaming); bad fit for heavy CPU computation - npm ecosystem: over 2 million packages ### Quick example ```js const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello from Node.js'); }); server.listen(3000, () => { console.log('Listening on port 3000'); }); ``` An HTTP server in 10 lines. No Apache, no Nginx config. Node.js handles all the networking through its built-in `http` module. ### How Node.js handles a request The JS thread is single. One execution context at a time. So what happens when 1,000 users hit your server at once? Node.js delegates blocking work - file reads, database queries, network calls - to libuv. libuv maintains a thread pool (4 threads by default) that performs actual I/O at the OS level. When the work finishes, libuv puts the callback into the event queue. The event loop picks it up and runs it on the JS thread. ``` Your JS Code | Node.js APIs (fs, http, net, crypto...) | libuv (event loop + thread pool) | OS (file system, network, timers) ``` The JS thread stays free the whole time the OS is doing actual work. That's how Node.js handles thousands of concurrent connections on one thread - most of the time it's just waiting for I/O, not computing. ### V8 and libuv V8 compiles JavaScript to native machine code. Not interpreted, not run through a slow bytecode layer - compiled. That's why Node.js is fast for JS execution. libuv is the other half. It's a C++ library originally written for Node.js, now used by other projects as well. It provides: - The event loop - Async file I/O (thread pool, 4 by default, configurable via `UV_THREADPOOL_SIZE`) - TCP/UDP sockets - DNS resolution - Timers (`setTimeout`, `setInterval`) Without libuv, Node.js would just be V8 with no way to communicate with the OS asynchronously. ### When Node.js struggles The single JS thread is a real constraint. Run a CPU-heavy operation - parsing a large JSON, image processing, an ML inference call - and the event loop blocks. Every other request waits. ```js // This freezes the event loop for all users while it runs app.get('/report', (req, res) => { const result = generateHeavyReport(); // blocks the JS thread res.json({ result }); }); ``` For CPU-intensive work, use Worker Threads (available since Node 12) or offload to a separate service. Node.js works well as an API gateway and coordinator, not as a computation engine. ### Where Node.js fits - REST APIs and GraphQL servers - WebSocket servers and real-time apps (chat, live updates, collaborative tools) - CLI tools and build scripts (webpack, Vite, ESLint all run on Node) - Serverless functions (AWS Lambda, Vercel, Cloudflare Workers) - Microservices that mostly do I/O The npm ecosystem is part of the value. Over 2 million packages means most problems already have a published solution. ### Common mistakes **Blocking the event loop with sync operations** ```js // Bad - blocks the entire server while reading const data = fs.readFileSync('./large-file.json'); // Good - libuv handles it, JS thread stays free fs.readFile('./large-file.json', (err, data) => { // runs when ready }); ``` **Assuming Node.js is multi-threaded** Node.js has one JS thread. `setTimeout` and `setInterval` don't run in parallel - they schedule callbacks. If the event loop is blocked, timers fire late. **Using Node.js for CPU tasks without Worker Threads** One CPU-bound request can slow down every other user's response. If you need heavy CPU work, use `worker_threads` or a child process. **Ignoring unhandled promise rejections** Since Node 15, an unhandled rejection crashes the process by default. Always add `.catch()` or use `try/catch` in async functions. ```js // Crashes the process in Node 15+ fetchUserData(userId); // async function, no error handling attached ``` ### Real-world usage - Express, Fastify, Koa - HTTP frameworks built on top of Node's `http` module - Next.js - SSR and API routes run in a Node.js process - Socket.io - real-time communication over WebSocket - NestJS - structured backend framework for larger applications - Tooling: Vite, webpack, TypeScript compiler, ESLint, Prettier I've seen teams pick Node.js for a data pipeline that was mostly waiting on database queries. It handled the concurrency without any additional infrastructure. ### Follow-up questions **Q:** What is the difference between Node.js and a browser's JavaScript engine? **A:** Both can use V8, but Node.js adds libuv for OS access (file system, networking) and has no DOM, `window`, or browser APIs. The browser has `document`, `fetch`, `localStorage`. Node has `fs`, `net`, `child_process`. **Q:** Why is Node.js single-threaded but still handles many connections? **A:** JS execution is single-threaded, but I/O is handled by libuv's thread pool and OS-level async calls. Node.js spends most of its time waiting for I/O, not computing. During that wait, the event loop picks up other callbacks. **Q:** What happens when the event loop is blocked? **A:** All pending requests wait. If the JS thread runs a 5-second computation, every response is delayed by those 5 seconds. This is why Node.js is not suited for CPU-intensive tasks without Worker Threads. **Q:** How many threads does Node.js actually use? **A:** One JS thread. libuv adds 4 pool threads by default (configurable via `UV_THREADPOOL_SIZE`). Network I/O uses OS-level async and doesn't go through the pool. A typical Node process shows 6-8 threads in `top` or `htop`. **Q:** Is libuv specific to Node.js? **A:** No. libuv is an independent open-source C++ library (libuv/libuv on GitHub). Node.js was the original reason it was created, but other runtimes and tools use it too. ## Examples ### Basic HTTP server ```js const http = require('http'); const server = http.createServer((req, res) => { if (req.url === '/health') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'ok' })); return; } res.writeHead(404); res.end('Not found'); }); server.listen(3000, () => console.log('Server on port 3000')); ``` No dependencies. Node's `http` module handles TCP connections, HTTP parsing, and keeps the server alive. ### Async file read with error handling ```js const fs = require('fs').promises; async function loadConfig(path) { try { const raw = await fs.readFile(path, 'utf8'); return JSON.parse(raw); } catch (err) { console.error('Config load failed:', err.message); return null; } } loadConfig('./config.json').then(config => { console.log('App name:', config?.name); }); ``` `fs.promises.readFile` hands the work to libuv's thread pool. The JS thread stays free until the file is ready. The `await` pauses only this async function, not the whole event loop. ### Event loop execution order ```js console.log('1 - sync'); setTimeout(() => console.log('3 - macrotask'), 0); Promise.resolve().then(() => console.log('2 - microtask')); console.log('4 - sync'); // Output: // 1 - sync // 4 - sync // 2 - microtask (Promise callback) // 3 - macrotask (setTimeout) ``` Microtasks (Promise callbacks) run before macrotasks (setTimeout), even with a 0ms delay. This surprises developers who expect `setTimeout(..., 0)` to run right after the current synchronous block.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.