Suggest an editImprove this articleRefine the answer for “What are the pros and cons of Node.js being single-threaded?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Being single-threaded gives Node.js a simple concurrency model and excellent I/O throughput, but makes it poor at CPU-heavy work and fragile to a single blocking call.** There are no race conditions or locks to reason about, and non-blocking I/O lets one thread serve many requests cheaply. The trade-off: one long synchronous operation, or one uncaught error, can stall or crash the entire process, and heavy computation must be offloaded to `worker_threads`, `child_process` or `cluster`.Shown above the full answer for quick recall.Answer (EN)ImageNode.js runs all JavaScript logic on a single thread through the event loop, while I/O is delegated to background threads via libuv. That single design choice creates a specific set of strengths and weaknesses. ## Theory ### TL;DR - No mutexes or race conditions between JS statements: a simple concurrency model - Excellent throughput for I/O-bound work; poor fit for CPU-heavy computation, which blocks the one thread - Cheap on resources compared to a thread-per-connection server, and easy to scale horizontally via `cluster` or PM2 - One uncaught error can crash the whole process, since everything shares that single thread ### Quick example ```javascript process.on('uncaughtException', (err) => { console.error('uncaught exception:', err); process.exit(1); // restart via a process manager like PM2 }); ``` ### Advantages ### 1. A simple concurrency model No mutexes, no race conditions between JavaScript statements. Developers reason about async callbacks, promises and `async`/`await` instead of thread synchronization. ### 2. High throughput for I/O-bound work Single-threaded execution plus non-blocking I/O means thousands of requests can be in flight at once. While one request waits on a database, the thread serves others. This fits REST APIs, microservices, real-time apps and proxy/streaming servers well. ### 3. Lower resource usage One thread costs far less memory and CPU than spawning a thread per connection, the classic Apache/PHP model. Node.js can serve heavy load on modest hardware. ### 4. Easy horizontal scaling Multiple processes can be started with the `cluster` module, PM2, or several Docker containers, achieving process-level parallelism while each process keeps the simple event-loop model. ### 5. Predictable execution Code inside a single JavaScript turn runs to completion before the next one starts; there is no need to coordinate shared memory between JS threads. ### Disadvantages ### 1. Poor fit for CPU-intensive work Compression, encryption, machine learning inference, heavy parsing, image or video processing all block the single thread while they run, so the server stops answering any other request until the computation finishes. Fix: move such work to `worker_threads`, a `child_process`, a task queue (e.g. BullMQ), or a separate service in another language. ### 2. Vulnerable to blocking calls Any synchronous call, `fs.readFileSync`, `JSON.parse` on a huge payload, a tight loop, can freeze the entire server for the duration of that call. One expensive request degrades every other request at the same time. ### 3. Manual work for true parallelism Using all CPU cores requires explicitly setting up `cluster` or `worker_threads`; Node.js does not parallelize automatically. ### 4. A steeper learning curve for the event loop Understanding callback queues, microtasks versus macrotasks, and event loop phases takes time; "callback hell" and unhandled promise rejections are common beginner mistakes. ### 5. One uncaught error can take down the process Because everything shares one thread, an unhandled exception can crash the whole server, not just one request. Mitigations: `try/catch` around risky code, a `process.on('uncaughtException', ...)` safety net, and a process manager like PM2 that restarts a crashed process. ### Summary | Category | Advantage | Disadvantage | | --- | --- | --- | | Simplicity | No locks, no race conditions | No built-in multithreading | | Performance | Excellent for I/O | Weak for CPU-bound work | | Resources | Minimal overhead | Heavy code blocks everything | | Scaling | Easy via clustering | Harder than true multithreading | | Debugging | Simple execution flow | Async logic needs event-loop understanding | ### Common mistakes - **Running CPU-bound algorithms directly in a request handler.** Offload them; do not let them share the thread that serves HTTP traffic. - **Skipping error handling on async code.** An unhandled rejection or exception can bring the whole process down. - **Assuming single-threaded means no scaling options.** Clustering, worker threads and horizontal scaling all remain available; they just have to be set up deliberately.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.