Identifying Memory Leaks in Request Objects
In this lesson, you will learn how to identify memory leaks caused by lingering request objects during high-concurrency load tests.
When your server handles thousands of requests per second, the "request" and "response" objects are usually cleaned up by the Garbage Collector (GC) as soon as the request ends. However, if you accidentally attach these objects to a long-lived scope—like a global array or a persistent event emitter—the memory cannot be reclaimed. Under high traffic, this creates a "memory leak" that will crash your server as the heap fills up.
The "Stuck" Request Pattern
Imagine a middleware that logs request metadata into a global cache to track active users. If you forget to remove the entry when the request finishes, the entire request object (and the massive closures attached to it) stays in RAM forever.
const activeRequests = [];
function loggingMiddleware(req, res, next) {
// Leaky: Adding the entire request object to a global array
activeRequests.push(req);
res.on('finish', () => {
// If you forget to splice this out, the memory leaks!
});
next();
}
Monitoring the Heap
To catch this, you need to perform a Load Test. Using a tool like autocannon or artillery, flood your server with requests while monitoring the heap. You can inspect this using Node's built-in memory reporting:
setInterval(() => {
const { heapUsed } = process.memoryUsage();
console.log(`Heap usage: ${Math.round(heapUsed / 1024 / 1024)} MB`);
}, 5000);
If you run a load test and notice the heapUsed climbs steadily and never drops back down after the traffic stops, you have a leak. To fix it, ensure that any data associated with a request is strictly tied to its lifecycle. Use the res.on('finish', ...) or res.on('close', ...) events to explicitly clear any references you've created. If the heap stabilizes after the test, your memory management is healthy.
Key Takeaway: If your heap usage shows a "staircase" pattern during load testing that doesn't reset after traffic subsides, you are likely holding onto request objects in long-lived variables.