| name | nodejs |
| description | Node.js backend patterns with async I/O and process management. Trigger: When building backend services, CLI tools, or server scripts. |
| license | Apache 2.0 |
| metadata | {"version":"1.0","type":"language","skills":["typescript"],"dependencies":{"node":">=18.0.0 <23.0.0"}} |
Node.js
Async I/O, process management, backend services with Node.js runtime.
Examples use TypeScript. For JavaScript, remove type annotations (: string, interface, <T>, Promise<T>) โ patterns apply identically.
When to Use
- Building backend services or REST/GraphQL APIs
- Writing CLI tools, build scripts, or automation tasks
- Managing long-running processes (workers, daemons)
- Handling file I/O, streams, or network operations
- Developing real-time applications (WebSockets, SSE)
Don't use for:
- CPU-intensive tasks (worker threads/separate processes)
- Browser code (javascript/typescript skills)
- Framework patterns (express, nest, hono skills)
Critical Patterns
โ
REQUIRED: Use async/await for I/O
All I/O operations must be asynchronous to avoid blocking the event loop.
import fs from 'fs';
const data = fs.readFileSync('/path/to/file');
import fs from 'fs/promises';
const data = await fs.readFile('/path/to/file', 'utf-8');
โ
REQUIRED: Environment variable management
Never hardcode configuration. Use environment variables with validation.
const config = {
port: parseInt(process.env.PORT || '3000', 10),
nodeEnv: process.env.NODE_ENV || 'development',
dbUrl: process.env.DATABASE_URL,
};
if (!config.dbUrl) {
throw new Error('DATABASE_URL environment variable is required');
}
โ
REQUIRED: Graceful shutdown
Handle SIGTERM and SIGINT signals for clean shutdowns.
const server = app.listen(3000);
process.on('SIGTERM', async () => {
console.log('SIGTERM received, closing server...');
server.close(() => {
console.log('HTTP server closed');
});
await db.close();
process.exit(0);
});
process.on('SIGINT', () => process.emit('SIGTERM' as any));
โ
REQUIRED: Error handling for unhandled rejections
Catch unhandled promise rejections globally.
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
process.exit(1);
});
Decision Tree
Building an HTTP server?
โ Use framework (express, hono, nest) or http.createServer for simple cases
โ See express, hono, nest skills for framework-specific patterns
Writing a CLI tool?
โ Use process.argv for simple args
โ Use commander or yargs for complex CLI with commands/options
โ Handle process.exit codes (0 = success, 1+ = error)
Long-running process (worker, daemon)?
โ Listen for SIGTERM/SIGINT for graceful shutdown
โ Implement health checks for process monitoring
โ Use PM2 or systemd for process management in production
File I/O operations?
โ Use fs/promises for async file operations
โ Use streams for large files to avoid memory issues
โ Handle ENOENT, EACCES errors explicitly
Child process management?
โ Use child_process.spawn() for streaming output
โ Use child_process.exec() for small output
โ Always handle 'exit', 'error', and 'close' events
Memory-intensive operations?
โ Use worker_threads for CPU-bound tasks
โ Monitor process.memoryUsage() for leaks
โ Implement backpressure for streams
Edge Cases
-
Unhandled rejections: .catch() or try/catch. Use process.on('unhandledRejection') as fallback.
-
Memory leaks: --inspect flag with Chrome DevTools. Common: event listeners not removed, closures, unbounded caches.
-
Child processes: Don't auto-exit with parent. Listen for 'exit' event, kill explicitly.
-
File descriptors: OS limits (default ~1024). Use ulimit -n or connection pooling.
-
Event loop blocking: CPU tasks block loop. Use worker threads or setImmediate().
Checklist
Example
import http from 'http';
import fs from 'fs/promises';
import path from 'path';
const config = {
port: parseInt(process.env.PORT || '3000', 10),
dataDir: process.env.DATA_DIR || './data',
};
const server = http.createServer(async (req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
return;
}
try {
const filePath = path.join(config.dataDir, 'data.json');
const data = await fs.readFile(filePath, 'utf-8');
res.writeHead(200, { 'Content-Type': });
res.(data);
} (: ) {
(error. === ) {
res.(, { : });
res.();
} {
.(, error);
res.(, { : });
res.();
}
}
});
server.(config., {
.();
});
process.(, {
.();
server.( {
.();
process.();
});
});
process.(, process.( ));
process.(, {
.(, reason);
process.();
});
process.(, {
.(, error);
process.();
});
Resources