<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm" -->

---
title: Stop Calling Node.js “Single-Threaded”: A Look Under the...
description: Node.js is commonly labeled 'single-threaded,' but that description is misleading. While JavaScript itself runs on a single call stack, Node.js delegates slow...
canonical: https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Stop Calling Node.js “Single-Threaded”: A Look Under the Hood | daily.dev
og:description: Node.js is commonly labeled 'single-threaded,' but that description is misleading. While JavaScript itself runs on a single call stack, Node.js delegates slow...
og:url: https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm
og:image: https://api.daily.dev/og/posts/OFSmHBJmM.png
og:image:alt: Stop Calling Node.js “Single-Threaded”: A Look Under the Hood
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Stop Calling Node.js “Single-Threaded”: A Look Under the Hood

**[Medium](https://daily.dev/sources/medium_js)** · 8 min read · 6 upvotes · 0 comments

## Summary

Node.js is commonly labeled 'single-threaded,' but that description is misleading. While JavaScript itself runs on a single call stack, Node.js delegates slow I/O and timer operations to libuv, a C library that interfaces with the OS. This walkthrough traces how setTimeout callbacks and Promises are handled differently: timers are registered in libuv's min-heap and their callbacks land in the macrotask queue, while Promise resolutions go to the microtask queue. The event loop always drains all microtasks before picking up a single macrotask, which explains execution order surprises. Two code examples with step-by-step output traces illustrate the call stack, timer system, microtask queue, and macrotask queue interactions. A caveat is noted: a microtask that continuously spawns new microtasks can starve the event loop indefinitely.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@kami_Writes/stop-calling-node-js-single-threaded-a-look-under-the-hood-aec856be4190>

## Questions this post answers

### Why does console.log output appear in the order 1,3,5,2,4 when two setTimeout calls with 0ms delay are mixed with synchronous console.log statements?

Synchronous code always runs first because it stays on the call stack, while setTimeout callbacks are handed off to libuv's timer system and only placed on the callback queue once their delay expires and the current script finishes. Since all synchronous console.log calls execute before the event loop checks the callback queue, they print first, followed by the timer callbacks in order.

_Developers puzzling over async output order often revisit event loop mechanics on daily.dev before debugging timing bugs._

### Do microtasks or macrotasks run first in the Node.js event loop when both a Promise.then and a setTimeout are pending?

Microtasks always run before the next macrotask. The event loop drains the entire microtask queue, including Promise.then, catch, and finally callbacks, before processing even a single macrotask like a setTimeout or setInterval callback, so promise resolutions consistently print before timer callbacks scheduled at the same time.

_Anyone debugging promise-versus-timeout ordering can dig deeper into async queue behavior on daily.dev._

### Can a Node.js server freeze if a microtask keeps generating new microtasks?

Yes, if a microtask generates another microtask, the event loop stays on the microtask queue and executes each new one before moving on, since it never touches a macrotask while any microtask remains. This means it can indefinitely delay processing user requests or UI rendering, effectively freezing the server if the chain of microtasks never ends.

_Teams hardening Node.js services against event-loop starvation track patterns like this on daily.dev._

## Similar posts on daily.dev

- [How the JavaScript Runtime Schedules Callbacks: A Look at the Event Loop](https://daily.dev/posts/how-the-javascript-runtime-schedules-callbacks-a-look-at-the-event-loop-qkr1ufg7o) · Medium · 4 upvotes · 0 comments
- [JavaScript Event Loop Explained: Queue Tracing and Debugging Guide](https://daily.dev/posts/javascript-event-loop-explained-queue-tracing-and-debugging-guide-sa0thbcrm) · SitePoint · 147 upvotes · 4 comments
- [JavaScript Microtasks vs Tasks: What Runs First?](https://daily.dev/posts/javascript-microtasks-vs-tasks-what-runs-first--zlnrvrlzg) · Medium · 131 upvotes · 5 comments
- [Mastering the JavaScript Event Loop](https://daily.dev/posts/mastering-the-javascript-event-loop-xrcdqa1q5) · freeCodeCamp · 26 upvotes · 0 comments
- [Slint and the Node.js Event Loop](https://daily.dev/posts/slint-and-the-node-js-event-loop-3ayskjayl) · Slint · 78 upvotes · 1 comments

---

Tags: [#javascript](https://daily.dev/tags/javascript), [#nodejs](https://daily.dev/tags/nodejs)

[View this post on daily.dev](https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Stop Calling Node.js “Single-Threaded”: A Look Under the Hood","url":"https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm"},"datePublished":"2026-07-23T20:08:32.414Z","dateModified":"2026-09-13T21:18:50.902Z","description":"Node.js is commonly labeled 'single-threaded,' but that description is misleading. While JavaScript itself runs on a single call stack, Node.js delegates slow...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ab1dadc9bce9ea809629cf77268fed53?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ab1dadc9bce9ea809629cf77268fed53?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":6},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"javascript,nodejs","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"Stop Calling Node.js “Single-Threaded”: A Look Under the Hood"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/stop-calling-node-js-single-threaded-a-look-under-the-hood-ofsmhbjmm#faq","mainEntity":[{"@type":"Question","name":"Why does console.log output appear in the order 1,3,5,2,4 when two setTimeout calls with 0ms delay are mixed with synchronous console.log statements?","acceptedAnswer":{"@type":"Answer","text":"Synchronous code always runs first because it stays on the call stack, while setTimeout callbacks are handed off to libuv's timer system and only placed on the callback queue once their delay expires and the current script finishes. Since all synchronous console.log calls execute before the event loop checks the callback queue, they print first, followed by the timer callbacks in order. Developers puzzling over async output order often revisit event loop mechanics on daily.dev before debugging timing bugs."}},{"@type":"Question","name":"Do microtasks or macrotasks run first in the Node.js event loop when both a Promise.then and a setTimeout are pending?","acceptedAnswer":{"@type":"Answer","text":"Microtasks always run before the next macrotask. The event loop drains the entire microtask queue, including Promise.then, catch, and finally callbacks, before processing even a single macrotask like a setTimeout or setInterval callback, so promise resolutions consistently print before timer callbacks scheduled at the same time. Anyone debugging promise-versus-timeout ordering can dig deeper into async queue behavior on daily.dev."}},{"@type":"Question","name":"Can a Node.js server freeze if a microtask keeps generating new microtasks?","acceptedAnswer":{"@type":"Answer","text":"Yes, if a microtask generates another microtask, the event loop stays on the microtask queue and executes each new one before moving on, since it never touches a macrotask while any microtask remains. This means it can indefinitely delay processing user requests or UI rendering, effectively freezing the server if the chain of microtasks never ends. Teams hardening Node.js services against event-loop starvation track patterns like this on daily.dev."}}]}
```

