π― Goal of This Note
Understand what a thread is, why Node.js runs in a single thread, and how the thread pool helps handle heavier tasks without blocking that thread.
π₯οΈ What Is a Process?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>What is a process?</title>
</head>
<body>
<div class="proc-info" id="procinfo">
<style>
.proc-info {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft: #e3ebfd;
--line: #ddd6c9;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
--mono-font: 'IBM Plex Mono', monospace;
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
padding: 2rem;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.proc-info[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c212b;
--accent: #5b8def;
--accent-soft: #202942;
--line: #2c313d;
}
.proc-info * { box-sizing: border-box; }
.proc-eyebrow {
font-family: var(--mono-font); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
color: var(--accent); text-align: center; margin: 1.5rem 0 0.3rem;
}
.proc-title {
font-family: var(--display-font); font-size: clamp(1.5rem, 5vw, 2rem); text-align: center;
margin: 0 0 0.5rem; letter-spacing: -0.01em;
}
.proc-sub { color: var(--ink-soft); font-size: 0.92rem; text-align: center; margin: 0 0 2rem; max-width: 440px; margin-left: auto; margin-right: auto; }
/* ---- causal chain ---- */
.proc-chain { display: flex; align-items: flex-start; justify-content: center; gap: 0.4rem; margin-bottom: 0.5rem; }
.proc-node { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; width: 128px; }
.proc-node-icon {
width: 56px; height: 56px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
border: 1px solid var(--line); background: var(--paper-alt); transition: border-color 0.25s, background 0.25s, transform 0.25s;
}
.proc-node-icon svg { width: 26px; height: 26px; color: var(--ink-soft); transition: color 0.25s; }
.proc-node.is-active .proc-node-icon { border-color: var(--accent); background: var(--accent-soft); transform: scale(1.08); }
.proc-node.is-active .proc-node-icon svg { color: var(--accent); }
.proc-node-label { font-size: 0.82rem; font-weight: 700; text-align: center; color: var(--ink-soft); }
.proc-node.is-active .proc-node-label { color: var(--accent); }
.proc-node-sub { font-size: 0.68rem; text-align: center; color: var(--ink-soft); line-height: 1.3; }
.proc-chain-arrow { color: var(--line); font-size: 1.2rem; margin-top: 1.4rem; transition: color 0.25s; }
.proc-chain-arrow.is-live { color: var(--accent); }
.proc-controls { display: flex; justify-content: center; margin: 1.6rem 0 2.4rem; }
.proc-btn {
font-family: var(--mono-font); font-size: 0.82rem; font-weight: 600; padding: 0.6rem 1.2rem;
border-radius: 5px; border: 1px solid var(--accent); background: var(--accent); color: #fff; cursor: pointer;
}
.proc-btn:disabled { opacity: 0.55; cursor: default; }
/* ---- activity list (proof) ---- */
.proc-proof-label { text-align: center; font-size: 0.78rem; color: var(--ink-soft); margin-bottom: 0.9rem; }
.proc-monitor { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; margin-bottom: 1.4rem; }
.proc-monitor-head {
display: flex; justify-content: space-between; padding: 0.5rem 0.9rem; background: var(--paper-alt);
font-size: 0.64rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft);
}
.proc-row {
display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.9rem; border-top: 1px solid var(--line);
background: var(--paper);
}
.proc-row svg { width: 16px; height: 16px; color: var(--ink-soft); flex-shrink: 0; }
.proc-row-name { flex: 1; font-size: 0.82rem; font-weight: 600; }
.proc-row-pid { font-family: var(--mono-font); font-size: 0.76rem; color: var(--ink-soft); }
.proc-row.is-new {
opacity: 0; transform: translateY(-8px);
transition: opacity 0.35s ease, transform 0.35s ease, background 0.3s;
}
.proc-row.is-new.is-shown { opacity: 1; transform: none; }
.proc-row.is-new.is-highlight { background: var(--accent-soft); }
.proc-row.is-new.is-highlight svg { color: var(--accent); }
.proc-row.is-new.is-highlight .proc-row-pid { color: var(--accent); }
.proc-code {
font-family: var(--mono-font); font-size: 0.82rem; background: var(--paper-alt); border: 1px solid var(--line);
border-radius: 6px; padding: 0.8rem 1rem; margin: 0 auto 2.2rem; max-width: 340px; text-align: center;
opacity: 0; transform: translateY(-6px); transition: opacity 0.35s ease, transform 0.35s ease;
}
.proc-code.is-shown { opacity: 1; transform: none; }
.proc-code .k { color: var(--ink-soft); }
.proc-code .v { color: var(--accent); font-weight: 700; }
@media (prefers-reduced-motion: reduce) {
.proc-info *, .proc-info *::before, .proc-info *::after { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<div class="proc-chain">
<div class="proc-node" data-node="1">
<div class="proc-node-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></svg></div>
<div class="proc-node-label">Node.js</div>
<div class="proc-node-sub">a C++ program under the hood</div>
</div>
<span class="proc-chain-arrow" data-arrow="1">β</span>
<div class="proc-node" data-node="2">
<div class="proc-node-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg></div>
<div class="proc-node-label">OS process</div>
<div class="proc-node-sub">same as Chrome, or anything else</div>
</div>
<span class="proc-chain-arrow" data-arrow="2">β</span>
<div class="proc-node" data-node="3">
<div class="proc-node-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 12.5 8 15l2 2.5"/><path d="m14 12.5 2 2.5-2 2.5"/></svg></div>
<div class="proc-node-label">process</div>
<div class="proc-node-sub">a global variable, free in every file</div>
</div>
</div>
<div class="proc-controls">
<button type="button" class="proc-btn" id="procRunBtn">βΆ node app.js</button>
</div>
<p class="proc-proof-label">See it happen at the OS level</p>
<div class="proc-monitor">
<div class="proc-monitor-head"><span>Process</span><span>PID</span></div>
<div class="proc-row">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
<span class="proc-row-name">Chrome</span>
<span class="proc-row-pid">1204</span>
</div>
<div class="proc-row">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/></svg>
<span class="proc-row-name">Text editor</span>
<span class="proc-row-pid">892</span>
</div>
<div class="proc-row">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
<span class="proc-row-name">Music player</span>
<span class="proc-row-pid">3357</span>
</div>
<div class="proc-row is-new" id="procNewRow">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></svg>
<span class="proc-row-name">node app.js</span>
<span class="proc-row-pid" id="procNewPid">β</span>
</div>
</div>
<div class="proc-code" id="procCode">
<span class="k">console.log(process.pid);</span> <span class="v" id="procCodeOut">// β</span>
</div>
</div>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<script>
(function () {
var root = document.getElementById('procinfo');
if (!root) return;
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') dark = true;
else if (bodyAttr === 'false') dark = false;
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) root.setAttribute('data-theme', 'dark');
var runBtn = root.querySelector('#procRunBtn');
var nodes = root.querySelectorAll('.proc-node');
var arrows = root.querySelectorAll('.proc-chain-arrow');
var newRow = root.querySelector('#procNewRow');
var newPid = root.querySelector('#procNewPid');
var code = root.querySelector('#procCode');
var codeOut = root.querySelector('#procCodeOut');
var running = false;
function clearChain() {
nodes.forEach(function (n) { n.classList.remove('is-active'); });
arrows.forEach(function (a) { a.classList.remove('is-live'); });
}
runBtn.addEventListener('click', function () {
if (running) return;
running = true;
runBtn.disabled = true;
clearChain();
newRow.classList.remove('is-shown', 'is-highlight');
code.classList.remove('is-shown');
var pid = Math.floor(Math.random() * 8000) + 1500;
var t = 0, step = 420;
setTimeout(function () {
nodes[0].classList.add('is-active');
}, t);
t += step;
setTimeout(function () {
nodes[0].classList.remove('is-active');
arrows[0].classList.add('is-live');
nodes[1].classList.add('is-active');
void newRow.offsetWidth;
newRow.classList.add('is-shown');
newPid.textContent = pid;
}, t);
t += step;
setTimeout(function () {
newRow.classList.add('is-highlight');
}, t);
t += step;
setTimeout(function () {
nodes[1].classList.remove('is-active');
arrows[0].classList.remove('is-live');
arrows[1].classList.add('is-live');
nodes[2].classList.add('is-active');
}, t);
t += step;
setTimeout(function () {
arrows[1].classList.remove('is-live');
codeOut.textContent = '// ' + pid;
code.classList.add('is-shown');
}, t);
t += step;
setTimeout(function () {
nodes[2].classList.remove('is-active');
running = false;
runBtn.disabled = false;
}, t + 400);
});
})();
</script>
</body>
</html>When you run Node.js, your computer starts a process β just a fancy word for "a program that's currently running."
Since Node.js is really a C++ program under the hood, running it creates a real, actual process at the operating system level β same as opening Chrome or any other app.
Because of this, Node gives you access to a built-in
processvariable in your code β it exists precisely because Node itself is an OS process. You'll use this later in the course.
π§΅ What Is a Thread?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>What is a thread?</title>
</head>
<body>
<div class="thread-info" id="threadinfo">
<style>
.thread-info {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft: #e3ebfd;
--line: #ddd6c9;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
--mono-font: 'IBM Plex Mono', monospace;
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
padding: 2rem;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.thread-info[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c212b;
--accent: #5b8def;
--accent-soft: #202942;
--line: #2c313d;
}
.thread-info * { box-sizing: border-box; }
.th-eyebrow {
font-family: var(--mono-font); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
color: var(--accent); text-align: center; margin: 1.5rem 0 0.3rem;
}
.th-title {
font-family: var(--display-font); font-size: clamp(1.5rem, 5vw, 2rem); text-align: center;
margin: 0 0 0.5rem; letter-spacing: -0.01em;
}
.th-sub { color: var(--ink-soft); font-size: 0.92rem; text-align: center; margin: 0 0 2.2rem; max-width: 420px; margin-left: auto; margin-right: auto; }
/* ---- thread lane ---- */
.th-lane-wrap { border: 1px solid var(--line); border-radius: 12px; padding: 1.4rem 1.1rem 1.2rem; margin-bottom: 1.4rem; background: var(--paper-alt); }
.th-lane-label { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 0.9rem; }
.th-lane { display: flex; align-items: center; gap: 0.4rem; }
.th-instr {
width: 42px; height: 42px; border-radius: 8px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
border: 1px solid var(--line); background: var(--paper);
font-family: var(--mono-font); font-weight: 700; font-size: 0.85rem; color: var(--ink-soft);
transition: border-color 0.2s, background 0.2s, color 0.2s, opacity 0.3s, transform 0.2s;
}
.th-instr.is-current { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); transform: scale(1.12); }
.th-instr.is-done { opacity: 0.3; }
.th-connector { flex: 1; height: 1px; background: var(--line); min-width: 8px; transition: background 0.2s; }
.th-connector.is-live { background: var(--accent); height: 2px; }
.th-cpu {
width: 54px; height: 54px; border-radius: 10px; flex-shrink: 0; margin-left: 0.2rem;
display: flex; align-items: center; justify-content: center;
border: 1px solid var(--line); background: var(--paper); transition: border-color 0.2s, background 0.2s, transform 0.2s;
}
.th-cpu svg { width: 26px; height: 26px; color: var(--ink-soft); transition: color 0.2s; }
.th-cpu.is-pulse { border-color: var(--accent); background: var(--accent-soft); transform: scale(1.1); }
.th-cpu.is-pulse svg { color: var(--accent); }
.th-controls { display: flex; justify-content: center; margin-bottom: 0.6rem; }
.th-btn {
font-family: var(--mono-font); font-size: 0.82rem; font-weight: 600; padding: 0.55rem 1.1rem;
border-radius: 5px; border: 1px solid var(--accent); background: var(--accent); color: #fff; cursor: pointer;
}
.th-btn:disabled { opacity: 0.55; cursor: default; }
.th-caption { text-align: center; font-size: 0.8rem; color: var(--ink-soft); min-height: 1.3em; margin: 0.7rem 0 2rem; }
@media (prefers-reduced-motion: reduce) {
.thread-info *, .thread-info *::before, .thread-info *::after { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<div class="th-lane-wrap">
<div class="th-lane-label">Thread</div>
<div class="th-lane" id="thLane">
<div class="th-instr" data-i="1">1</div>
<div class="th-connector"></div>
<div class="th-instr" data-i="2">2</div>
<div class="th-connector"></div>
<div class="th-instr" data-i="3">3</div>
<div class="th-connector"></div>
<div class="th-instr" data-i="4">4</div>
<div class="th-connector" id="thFinalConnector"></div>
<div class="th-cpu" id="thCpu">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20v2"/><path d="M12 2v2"/><path d="M17 20v2"/><path d="M17 2v2"/><path d="M2 12h2"/><path d="M2 17h2"/><path d="M2 7h2"/><path d="M20 12h2"/><path d="M20 17h2"/><path d="M20 7h2"/><path d="M7 20v2"/><path d="M7 2v2"/><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="8" y="8" width="8" height="8" rx="1"/></svg>
</div>
</div>
</div>
<div class="th-controls">
<button type="button" class="th-btn" id="thRunBtn">βΆ Run thread</button>
</div>
<p class="th-caption" id="thCaption"> </p>
</div>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<script>
(function () {
var root = document.getElementById('threadinfo');
if (!root) return;
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') dark = true;
else if (bodyAttr === 'false') dark = false;
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) root.setAttribute('data-theme', 'dark');
var runBtn = root.querySelector('#thRunBtn');
var instrs = root.querySelectorAll('.th-instr');
var connectors = root.querySelectorAll('.th-connector');
var cpu = root.querySelector('#thCpu');
var caption = root.querySelector('#thCaption');
var running = false;
function reset() {
instrs.forEach(function (n) { n.classList.remove('is-current', 'is-done'); });
connectors.forEach(function (c) { c.classList.remove('is-live'); });
cpu.classList.remove('is-pulse');
caption.textContent = '\u00a0';
}
runBtn.addEventListener('click', function () {
if (running) return;
running = true;
runBtn.disabled = true;
reset();
var step = 420;
instrs.forEach(function (instr, i) {
var t = i * step;
setTimeout(function () {
instrs.forEach(function (n) { n.classList.remove('is-current'); });
connectors.forEach(function (c) { c.classList.remove('is-live'); });
instr.classList.add('is-current');
connectors[i].classList.add('is-live');
caption.textContent = 'Instruction ' + instr.getAttribute('data-i') + ' is running';
}, t);
setTimeout(function () {
instr.classList.remove('is-current');
instr.classList.add('is-done');
connectors[i].classList.remove('is-live');
}, t + step - 60);
});
var cpuTime = instrs.length * step;
setTimeout(function () {
cpu.classList.add('is-pulse');
caption.textContent = 'Done β run one after another, in order';
}, cpuTime);
setTimeout(function () {
cpu.classList.remove('is-pulse');
running = false;
runBtn.disabled = false;
}, cpuTime + 700);
});
reset();
})();
</script>
</body>
</html>A thread is simply a sequence of instructions being run.
Think of it as a "box" where your code actually executes on the computer's processor β that's all you need to know for now.
β Node.js Runs on a Single Thread
π§΅ Node apps run inside just one thread β whether you have 10 users or 10 million, they all share it.
β οΈ Since there's only one thread, it's easy to accidentally block the whole app if you're not careful. This is one of Node's most important characteristics.
π What Happens When a Node App Starts
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node.js startup order</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@600&display=swap" rel="stylesheet">
</head>
<body>
<div class="noboot-info" id="noboot">
<style>
.noboot-info {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft: #e3ebfd;
--line: #ddd6c9;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
--mono-font: 'IBM Plex Mono', monospace;
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
padding: 2rem;
background: var(--paper);
}
.noboot-info[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c212b;
--accent: #5b8def;
--accent-soft: #202942;
--line: #2c313d;
}
.noboot-info * { box-sizing: border-box; }
.nb-title {
font-family: var(--display-font); font-size: 1.3rem; font-weight: 600; text-align: center;
margin: 0 0 1.6rem; color: var(--ink); letter-spacing: -0.01em;
}
.nb-row { display: flex; align-items: flex-start; justify-content: center; gap: 0.5rem; margin-bottom: 2rem; flex-wrap: wrap; }
.nb-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
.nb-node {
width: 60px; height: 60px; border-radius: 14px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
border: 1px solid var(--line); background: var(--paper-alt);
transition: border-color 0.25s, background 0.25s, transform 0.25s;
}
.nb-node svg { width: 26px; height: 26px; color: var(--ink-soft); transition: color 0.25s; }
.nb-item.is-active .nb-node { border-color: var(--accent); background: var(--accent-soft); transform: scale(1.12); }
.nb-item.is-active .nb-node svg { color: var(--accent); }
.nb-item.is-passed .nb-node { border-color: var(--accent); }
.nb-item.is-passed .nb-node svg { color: var(--accent); }
.nb-item.is-active .nb-node.is-loop svg { animation: nb-spin 1.1s linear infinite; }
@keyframes nb-spin { to { transform: rotate(360deg); } }
.nb-arrow { color: var(--line); flex-shrink: 0; transition: color 0.25s; margin-top: 21px; }
.nb-arrow svg { width: 18px; height: 18px; }
.nb-arrow.is-live { color: var(--accent); }
.nb-label { font-size: 0.72rem; font-weight: 700; color: var(--ink-soft); text-align: center; transition: color 0.25s; }
.nb-item.is-active .nb-label, .nb-item.is-passed .nb-label { color: var(--accent); }
.nb-controls { display: flex; justify-content: center; }
.nb-btn {
width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--accent); background: var(--accent);
color: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.nb-btn svg { width: 16px; height: 16px; margin-left: 2px; }
.nb-btn:disabled { opacity: 0.55; cursor: default; }
@media (prefers-reduced-motion: reduce) {
.noboot-info *, .noboot-info *::before, .noboot-info *::after { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
.nb-node.is-loop.is-active svg { animation: none; }
}
</style>
<div class="nb-row">
<div class="nb-item" data-item="1">
<div class="nb-node" data-n="1"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 12.5 8 15l2 2.5"/><path d="m14 12.5 2 2.5-2 2.5"/></svg></div>
<span class="nb-label">Top-level code</span>
</div>
<span class="nb-arrow" data-a="1"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg></span>
<div class="nb-item" data-item="2">
<div class="nb-node" data-n="2"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v6"/><path d="M16.76 3a2 2 0 0 1 1.8 1.1l2.23 4.479a2 2 0 0 1 .21.891V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9.472a2 2 0 0 1 .211-.894L5.45 4.1A2 2 0 0 1 7.24 3z"/><path d="M3.054 9.013h17.893"/></svg></div>
<span class="nb-label">Modules</span>
</div>
<span class="nb-arrow" data-a="2"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg></span>
<div class="nb-item" data-item="3">
<div class="nb-node" data-n="3"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg></div>
<span class="nb-label">Callbacks</span>
</div>
<span class="nb-arrow" data-a="3"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg></span>
<div class="nb-item" data-item="4">
<div class="nb-node is-loop" data-n="4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"/><path d="M16 16h5v5"/></svg></div>
<span class="nb-label">Event loop</span>
</div>
</div>
<div class="nb-controls">
<button type="button" class="nb-btn" id="nbRunBtn" aria-label="Run">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
</button>
</div>
</div>
<script>
(function () {
var root = document.getElementById('noboot');
if (!root) return;
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') dark = true;
else if (bodyAttr === 'false') dark = false;
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) root.setAttribute('data-theme', 'dark');
var btn = root.querySelector('#nbRunBtn');
var items = root.querySelectorAll('.nb-item');
var arrows = root.querySelectorAll('.nb-arrow');
var running = false;
var spinTimeoutId = null;
function reset() {
items.forEach(function (it) { it.classList.remove('is-active', 'is-passed'); });
arrows.forEach(function (a) { a.classList.remove('is-live'); });
if (spinTimeoutId) { clearTimeout(spinTimeoutId); spinTimeoutId = null; }
}
btn.addEventListener('click', function () {
if (running) return;
running = true;
btn.disabled = true;
reset();
var step = 480;
var lastIndex = items.length - 1;
items.forEach(function (it, i) {
var t = i * step;
setTimeout(function () {
items.forEach(function (o) { o.classList.remove('is-active'); });
arrows.forEach(function (a) { a.classList.remove('is-live'); });
for (var j = 0; j < i; j++) { items[j].classList.add('is-passed'); }
if (i > 0) arrows[i - 1].classList.add('is-live');
it.classList.add('is-active');
if (i === lastIndex) {
spinTimeoutId = setTimeout(function () {
it.classList.remove('is-active');
it.classList.add('is-passed');
spinTimeoutId = null;
}, 5000);
}
}, t);
});
setTimeout(function () {
for (var j = 0; j < lastIndex; j++) { items[j].classList.add('is-passed'); }
running = false;
btn.disabled = false;
}, lastIndex * step + 350);
});
})();
</script>
</body>
</html>βΆοΈ Top-level code runs first β anything not inside a callback (e.g. reading files at the top of
index.js)π¦ Modules load β core, custom, and third-party
π Callbacks get registered β e.g. the function passed to
http.createServer()is set up, but doesn't run yetπ The event loop starts β this is where most of the actual work happens; the "heart" of Node
β οΈ The Problem: Some Tasks Are Too Heavy
Certain operations would block the single thread if run directly in the event loop β bad for a server handling many users.
β The Solution: Thread Pool
π§° Provided by libuv, the thread pool gives Node 4 extra threads (configurable up to 128).
π The event loop automatically offloads heavy tasks to these threads, keeping the main thread free.
π€ This happens automatically β developers don't choose what gets offloaded.
π What Gets Offloaded?
π Category | π Examples |
|---|---|
π File system | Reading/writing files |
π Cryptography | Password hashing, encryption |
ποΈ Compression | Zipping/unzipping |
π DNS lookups | Domain β IP resolution |
These are exactly the tasks most likely to block the main thread β so Node routes them to the thread pool instead.
π Key Takeaways
π Concept | β Explanation |
|---|---|
π» Process | A running instance of a program (Node itself, as a C++ program) |
π§΅ Thread | A sequence of instructions β "where code executes" |
π§΅ Single thread | True no matter how many users β makes blocking code dangerous |
βΆοΈ Top-level code | Runs first, immediately, not inside a callback |
π Event loop | Starts after setup; handles ongoing work β Node's "heart" |
π§° Thread pool | 4 (up to 128) extra threads from libuv, for heavy tasks |
π€ Auto-offloading | Node/libuv decide automatically β not developer-controlled |
π Offloaded tasks | File ops, crypto, compression, DNS lookups |