Backend7 min read

Node.js

JavaScript runtime for server-side development - event-driven, non-blocking I/O makes it ideal for APIs, real-time apps, and microservices.

Node.jsJavaScriptEvent LoopStreamsRuntime

skill: Node.js category: Backend tags: [Node.js, JavaScript, Event Loop, Streams, Runtime] readingTime: 7

Node.js excels at I/O-bound tasks - APIs, streaming, real-time. For CPU-bound work (image processing, ML inference), use Worker Threads or delegate to a separate service in Python/Go. For type safety, use TypeScript from day one.

Workflow

  1. Set up a Node.js project with TypeScriptTypeScript catches type errors at compile time and improves IDE experience - worth the setup cost for any project larger than a script.
  2. Understand and use the event loop correctlyNode's single-threaded event loop means a blocked main thread blocks all requests. Never block with sync I/O or heavy computation.
  3. Handle errors properlyUnhandled promise rejections crash the process in Node 15+. All async code needs try/catch or .catch() handlers.
  4. Stream large data instead of bufferingLoading a 1GB CSV into memory crashes the process. Streams process data in chunks at constant memory.
  5. Scale with cluster modeNode.js is single-threaded. Cluster mode spawns one worker per CPU core - fully utilizing a multi-core server.

Output Format

Production Node.js service with TypeScript, async error handling, streaming, and cluster mode.

src/
├── index.ts          # Entry point + cluster primary
├── server.ts         # HTTP server setup
├── routes/           # Route handlers
├── middleware/       # Error handling, auth, logging
├── services/         # Business logic
└── utils/
    ├── asyncHandler.ts
    └── gracefulShutdown.ts

Examples

Input

Output

Edge Cases & Gotchas

  • EventEmitter memory leak - Adding listeners in a loop without removing them leaks memory. Use emitter.setMaxListeners(n) or emitter.removeAllListeners() on cleanup.
  • Timer callback after process exit - Timers (setInterval) prevent clean process exit. Always clearInterval in SIGTERM handlers.
  • require() cache in long-running processes - Modules are cached after first require(). For hot-reloading config, delete require.cache[require.resolve('./config')] before re-requiring.
  • DNS lookup blocks - dns.lookup() uses the thread pool (not async DNS). Under heavy load, DNS lookups queue and cause latency. Use dns.resolve() which is truly async.

When to Break These Rules

  • Use Go or Rust for extremely CPU-bound workloads - Node.js Worker Threads help but aren't as efficient as natively compiled code.
  • Use Python for ML inference pipelines - the ecosystem (PyTorch, NumPy, scikit-learn) is incomparable in Node.js.

Reference Files

  • https://nodejs.org/en/docs/
  • https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.