Node.js Debugging Deep Dive — Complete Guide to Inspector and Chrome DevTools
In this tutorial, you will learn about Node.js Debugging Deep Dive. We cover key concepts, practical examples, and best practices to help you master this topic.
Node.js debugging deep dive covers the built-in inspector protocol, Chrome DevTools integration, breakpoints, step debugging, source maps, memory profiling, and performance analysis.
What You'll Learn
By the end of this tutorial, you'll debug Node.js applications using the inspector, set breakpoints, inspect async call stacks, analyze heap snapshots, profile CPU usage, and debug remote containers.
Why Deep Debugging Matters
console.log debugging is slow and limited. The inspector protocol gives you full visibility into running processes, memory, CPU, and async context, reducing debugging time dramatically.
Real-World Use
A production incident with memory growth is resolved by taking heap snapshots at intervals, comparing them in Chrome DevTools, and identifying a forgotten cache that never evicts entries.
Debugging Path
flowchart LR
A[Error Handling] --> B[Debugging Deep]
B --> C[Profiling]
C --> D[Memory Leaks]
D --> E[Performance]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Starting the Inspector
Run Node.js with the --inspect flag to enable debugging. Attach Chrome DevTools via chrome://inspect.
// Run with: node --inspect app.js
// Or for break on start: node --inspect-brk app.js
const express = require("express");
const app = express();
app.get("/", (req, res) => {
const data = { message: "Hello Debug!" };
// Set a breakpoint here in DevTools
debugger; // This triggers a breakpoint when inspector is attached
res.json(data);
});
app.listen(3000);
Using Chrome DevTools
Connect to the Node.js Process from Chrome DevTools for full debugging experience.
// 1. Start: node --inspect-brk app.js
// 2. Open Chrome and go to chrome://inspect
// 3. Click "Open dedicated DevTools for Node"
// 4. The debugger pauses at the first line
function calculateTotal(items) {
return items.reduce((sum, item) => {
debugger; // Breakpoint inside reduce
return sum + item.price;
}, 0);
}
const result = calculateTotal([{ price: 10 }, { price: 20 }]);
console.log("Total:", result);
Source Maps for Debugging
Enable source maps to debug TypeScript or bundled code in its original form.
// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false
}
}
// Run with source map support
// node --enable-source-maps dist/app.js
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("Debugger"));
Async Call Stack Debugging
The inspector preserves async call stacks, showing the full chain of async operations.
async function fetchUser(userId) {
const data = await fetchFromDB(userId);
debugger; // Check the async call stack here
return data;
}
async function fetchFromDB(id) {
return new Promise((resolve) => {
setTimeout(() => resolve({ id, name: "Alice" }), 100);
});
}
fetchUser(42);
// In DevTools, the async call stack shows fetchUser -> fetchFromDB
Memory Heap Snapshots
Take heap snapshots to find memory leaks and understand object retention.
// Take heap snapshot via DevTools Memory tab
// Or programmatically:
const v8 = require("node:v8");
const fs = require("node:fs");
// Take snapshot
const snapshotStream = v8.getHeapSnapshot();
const fileStream = fs.createWriteStream("/tmp/heap.heapsnapshot");
snapshotStream.pipe(fileStream);
// Load the .heapsnapshot file in Chrome DevTools Memory tab
// Compare snapshots to find growing objects
Common Mistakes
1. Using console.log Instead of the Debugger
console.log alters code behavior, litters output, and does not show object internals. Use the inspector.
2. Not Using --inspect-brk for Early Code
When debugging startup code, use --inspect-brk to pause before any code executes.
3. Ignoring Async Stack Traces
Without inspector, async errors show limited stack traces. The inspector preserves the full async chain.
4. Debugging Production Without Caution
The inspector exposes internals. Do not enable --inspect in production without security controls.
5. Forgetting Source Maps for TypeScript/JSX
Debugging compiled code without source maps shows minified output. Enable source maps.
Practice Questions
1. What is the difference between --inspect and --inspect-brk?
--inspect starts the inspector and runs code. --inspect-brk pauses at the first line before any code executes.
2. How do you attach Chrome DevTools to a Node.js process?
Open Chrome, go to chrome://inspect, and click "Open dedicated DevTools for Node".
3. What is the debugger statement?
A statement that triggers a breakpoint when a debugger is attached. Ignored when no debugger is present.
4. How do you debug TypeScript code?
Enable source maps in tsconfig.json and run with --enable-source-maps flag.
5. Challenge: Debug a memory leak by comparing heap snapshots programmatically.
const v8 = require("node:v8");
const fs = require("node:fs");
const snapshots = [];
function takeSnapshot(label) {
const stream = v8.getHeapSnapshot();
const file = fs.createWriteStream(`/tmp/heap-${label}.heapsnapshot`);
stream.pipe(file);
snapshots.push(label);
console.log(`Snapshot ${label} saved`);
}
takeSnapshot("before");
let leak = [];
for (let i = 0; i < 100000; i++) leak.push({ data: new Array(1000).fill("x") });
takeSnapshot("after");
// Compare in DevTools Memory tab
FAQ
Mini Project: Debugging Script with Automated Snapshot
Build a script that takes periodic heap snapshots for analysis.
const v8 = require("node:v8");
const fs = require("node:fs");
const path = require("node:path");
class HeapMonitor {
constructor(dir = "/tmp/heap-snapshots") {
this.dir = dir;
fs.mkdirSync(dir, { recursive: true });
this.count = 0;
}
takeSnapshot(label = "") {
const timestamp = Date.now();
const file = path.join(this.dir, `snapshot-${this.count}-${label}-${timestamp}.heapsnapshot`);
const stream = v8.getHeapSnapshot();
const writeStream = fs.createWriteStream(file);
stream.pipe(writeStream);
this.count++;
return file;
}
start(intervalMs = 30000) {
return setInterval(() => this.takeSnapshot("auto"), intervalMs);
}
}
What's Next
Node.js Profiling Node.js Memory Leaks Node.js Performance
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro