Node.js Profiling.
Sub-Millisecond Performance: Profiling and Optimizing Node.js Under Load
Your Node.js API handles 500 requests per second without breaking a sweat. Then you add a logging middleware. Suddenly, it maxes out at 300 requests per second. You didn't add much code—just a few JSON.stringify calls.
This is the invisible tax of performance. A single optimization might be "only" 2ms per request. At 500 requests/second, that's 1,000 milliseconds of cumulative wasted time every second. Ten small inefficiencies compound to become a bottleneck.
The only way to find these invisible taxes is **profiling**. Not guessing. Not intuition. Profiling: running your code under load, measuring CPU and memory usage, and identifying exactly where time is spent.
The Problem: Invisible Inefficiencies
Your code has hot paths—functions that run thousands of times per minute. If a hot path is 1ms slower than optimal, that's 1,000ms wasted per minute. The problem is that inefficiencies are **invisible** without instrumentation.
For OrdersPilot's webhook handler, I guessed the bottleneck was database writes. Latency was at 120ms. Only when I profiled the actual code did I discover the real culprit: **JSON serialization in logs**. The handler was logging every event, and each log call did `JSON.stringify` on the entire order object (hundreds of fields).
The Solution: Profiling Tools
Clinic.js
The gold standard. Visualizes CPU, memory, and event loop delays in interactive reports.
0x
Flamegraph generator. Shows exactly which functions are wide (slow) or narrow (fast).
Autocannon
Load testing tool. Simulates concurrent requests to profile your app under real pressure.
Case Study: OrdersPilot Optimization
Before Optimization
After Optimization
The Optimization Path
// 1. Async Logging & Selective Serialization
// Log IDs, not full objects
logger.info({ orderId, event });
// Serialize only needed fields for external payloads
const payload = {
orderId: order._id,
status: order.status,
timestamp: Date.now()
};// 2. Connection Pooling (MongoDB)
const mongoClient = new MongoClient(url, {
maxPoolSize: 50,
minPoolSize: 10,
maxIdleTimeMS: 60000
});The Profiling Checklist
Lessons Learned
Profiling Before Optimizing Saves Weeks
I could have spent weeks on database optimizations. Profiling found the real culprit (log serialization) in 30 minutes.
80/20 Rule Is Real
The top 3 bottlenecks accounted for 90% of the latency. Focus on the biggest first.
Event Loop Blocking Is Silent
When synchronous work blocks the event loop, requests just 'feel slow' because they queue and wait. Profiling reveals these hidden queues.
Performance optimization is systematic, not mystical. Measure, profile, identify, optimize, repeat. Without profiling, you're just guessing.