Node.js is amazing for shipping fast. It's also amazing at letting you ship broken things fast.
I've built a lot of broken things. Here are the patterns that make Node.js systems not break.
Pattern 1: EventEmitter for Internal Pub/Sub
import { EventEmitter } from 'events';
const orderEvents = new EventEmitter();
async function createOrder(userId, items) {
const order = await db.orders.create({ userId, items });
orderEvents.emit('order:created', order);
return order;
}
orderEvents.on('order:created', async (order) => {
await sendConfirmationEmail(order).catch(err => logger.error('Email failed', err));
});
orderEvents.on('order:created', async (order) => {
await logAnalytics('order_created', order).catch(err => logger.error('Analytics failed', err));
});
Result: Order creation returns in 50ms. Side effects async. If email fails, order still succeeded.
Pattern 2: Worker Threads for CPU-Bound Tasks
import { Worker } from 'worker_threads';
const workers = Array(os.cpus().length).fill(null).map(() => new Worker('./worker.js'));
let currentWorker = 0;
function processImage(imageBuffer) {
return new Promise((resolve, reject) => {
const worker = workers[currentWorker];
currentWorker = (currentWorker + 1) % workers.length;
const timer = setTimeout(() => reject(new Error('Worker timeout')), 30000);
worker.once('message', (result) => { clearTimeout(timer); resolve(result); });
worker.once('error', reject);
worker.postMessage({ imageBuffer });
});
}
Result: Heavy computation doesn't block the main thread.
Pattern 3: Domain-Specific Error Classes
class AppError extends Error {
constructor(message, statusCode, code) {
super(message);
this.statusCode = statusCode;
this.code = code;
}
}
class NotFoundError extends AppError {
constructor(message) { super(message, 404, 'NOT_FOUND'); }
}
class ValidationError extends AppError {
constructor(message) { super(message, 400, 'VALIDATION_ERROR'); }
}
app.get('/users/:id', async (req, res, next) => {
try {
const user = await getUser(req.params.id);
res.json(user);
} catch (err) {
if (err instanceof AppError) {
res.status(err.statusCode).json({ error: err.message });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
Pattern 4: Connection Pooling
const pool = new pg.Pool({
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
async function getUser(id) {
const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
return result.rows[0];
}
Pattern 5: Circuit Breaker
class CircuitBreaker {
constructor(fn, options = {}) {
this.fn = fn;
this.failureThreshold = options.failureThreshold || 5;
this.resetTimeout = options.resetTimeout || 60000;
this.state = 'CLOSED';
this.failureCount = 0;
this.lastFailureTime = null;
}
async call(...args) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await this.fn(...args);
this.failureCount = 0;
this.state = 'CLOSED';
return result;
} catch (err) {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) this.state = 'OPEN';
throw err;
}
}
}
Pattern 6: Graceful Shutdown
async function gracefulShutdown() {
server.close(async () => {
logger.info('Server closed');
});
const forceShutdown = setTimeout(() => process.exit(1), 30000);
try {
await db.close();
await redis.quit();
clearTimeout(forceShutdown);
process.exit(0);
} catch (err) {
process.exit(1);
}
}
process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);
The Meta Pattern: Async Error Handling
function asyncHandler(fn) {
return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
}
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await db.getUser(req.params.id);
res.json(user);
}));
app.use((err, req, res, next) => {
logger.error('Unhandled error', err);
res.status(500).json({ error: 'Internal server error' });
});
These aren't fancy patterns. They're the ones that keep systems running at 3am without pages.








