Debugging Node.js Applications
1. Using console.log for Debugging
| Tip | Detail |
|---|---|
| Tagged logs | console.log("[user]", user) |
| Inspect deeply | console.dir(obj, { depth: null, colors: true }) |
| Tables | console.table(rows) |
| Trace | console.trace("got here") |
2. Using debugger Statement
| Statement | Effect |
|---|---|
debugger; | Pauses when an inspector is attached |
3. Using Node Inspector (--inspect flag)
| Flag | Behavior |
|---|---|
--inspect | Listen on 127.0.0.1:9229 |
--inspect=0.0.0.0:9229 | Bind specific addr |
--inspect-wait | Wait for debugger before script start v22+ |
4. Using node --inspect-brk
| Flag | Behavior |
|---|---|
--inspect-brk | Pause on first line until debugger connects |
5. Using Chrome DevTools (chrome://inspect)
Connect Workflow
- Run
node --inspect-brk app.js - Open
chrome://inspectin Chrome/Edge - Click "Inspect" on the listed target
- Use Sources, Profiler, Memory tabs
6. Using VS Code Debugger (launch.json)
Example: launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug app",
"program": "${workspaceFolder}/src/index.js",
"skipFiles": ["<node_internals>/**"],
"env": { "NODE_ENV": "development" }
},
{ "type": "node", "request": "attach", "name": "Attach", "port": 9229 }
]
}
7. Using Debug Module
Example
import createDebug from "debug";
const debug = createDebug("app:db");
debug("query %o", q);
// DEBUG=app:* node app.js
8. Setting Breakpoints
| Type | Description |
|---|---|
| Line | Click gutter in DevTools/VS Code |
| Conditional | Break only when expression is true |
| Logpoint | Print without pausing |
| Exception | Pause on caught/uncaught throws |
9. Profiling CPU Usage (--prof flag)
| Flag | Effect |
|---|---|
--prof | Generates V8 tick log file |
--cpu-prof | Writes .cpuprofile (DevTools) |
--cpu-prof-dir=./profs | Output directory |
10. Analyzing Profile Output (--prof-process)
11. Memory Leak Detection
| Tool | Use |
|---|---|
| Heap snapshots | v8.writeHeapSnapshot() + Chrome DevTools |
--heap-prof | Sampling heap profile |
--inspect + Memory tab | Compare snapshots |
| Common causes | Listener leaks, growing caches, closures over big objects |
12. Using Clinic.js for Diagnostics
| Tool | Diagnoses |
|---|---|
clinic doctor | Symptom-based analysis |
clinic flame | Flamegraph (CPU) |
clinic bubbleprof | Async bottlenecks |
clinic heapprofiler | Heap allocation |
13. Using llnode for Post-Mortem Debugging
| Tool | Use |
|---|---|
llnode | LLDB plugin to inspect Node core dumps |
--abort-on-uncaught-exception | Generate core dump on crash |