Tracking down memory leaks with node.js has always been a challenge. The following discusses how to track memory leaks from within a node application itself with the help of two awesome node modules – memwatch and heapdump.


memory leak


First, a trivial sample leak:

var http = require('http');

var server = http.createServer(function (req, res) {
 for (var i=0; i<1000; i++) {
   server.on('request', function leakyfunc() {});

 res.end('Hello World\n');
}).listen(1337, '');
console.log('Server running at Process PID: ',;

Every request that we get here adds another 1,000 leaky listeners.

If we hit this continuously with while true; do curl; done in one shell, and in another shell view our process: top -pid <process pid> we will see very high and erratic memory usage for this node process.

Our node process has gone wild. So how do you diagnose from here?

Memory leak detection

The memwatch module is great for detecting memory leaks. Let’s install into our app as follows: npm install --save memwatch.

Then, in our code, add:

var memwatch = require('memwatch');

and also a listener for the ‘leak’ event:

memwatch.on('leak', function(info) {
 console.error('Memory leak detected: ', info);

Now when we run our test again, we see the following emitted:

 start: Fri Jan 02 2015 10:38:49 GMT+0000 (GMT),
 end: Fri Jan 02 2015 10:38:50 GMT+0000 (GMT),
 growth: 7620560,
 reason: 'heap growth over 5 consecutive GCs (1s) - -2147483648 bytes/hr'

Memwatch has detected that memory leak!

Memwatch defines a leak event as:

A leak event will be emitted when your heap usage has increased for five consecutive garbage collections.’

See memwatch for more details.

Memory leak analysis

So we’ve detected that we have a memory leak – great! But what now? The next step is to find where your leak is. Let’s see two ways of doing this.

Memwatch heap diff

You can get heap usage and a heap diff from memwatch itself. See the documentation here.

For example, we could do a heap dump alternatively between leak events, e.g.

var hd;
memwatch.on('leak', function(info) {
 if (!hd) {
   hd = new memwatch.HeapDiff();
 } else {
   var diff = hd.end();
   console.error(util.inspect(diff, true, null));
   hd = null;

This will give us some more information:

{ before: {
   nodes: 244023,
   time: Fri Jan 02 2015 12:13:11 GMT+0000 (GMT),
   size_bytes: 22095800,
   size: '21.07 mb' },
 after: {
   nodes: 280028,
   time: Fri Jan 02 2015 12:13:13 GMT+0000 (GMT),
   size_bytes: 24689216,
   size: '23.55 mb' },
 change: {
   size_bytes: 2593416,
   size: '2.47 mb',
   freed_nodes: 388,
   allocated_nodes: 36393,
   [ { size_bytes: 0,
   '+': 0,
   what: '(Relocatable)',
   '-': 1,
   size: '0 bytes' },
   { size_bytes: 0,
   '+': 1,
   what: 'Arguments',
   '-': 1,
   size: '0 bytes' },
   { size_bytes: 2856,
   '+': 223,
   what: 'Array',
   '-': 201,
   size: '2.79 kb' },
   { size_bytes: 2590272,
   '+': 35987,
   what: 'Closure',
   '-': 11,
   size: '2.47 mb' },

So between leak events here, we see that the heap has grown by 2.47MB, and the culprit here is 'Closure'. Note that if your leak is a specific class, the what may be your class name here, in which case that may be enough information for you to debug the leak from there.

However, in our case above, the only information we have is that our leak is in a closure, which is good but not really much help in a non-trivial app.

So where to from here? Enter heapdump.


node-heapdump is an awesome module. It can be used to make a dump of the V8 heap, which you can then inspect in Chrome Devtools. You can also compare heap snapshots in DevTools, which make it easier again to figure out where your leak is. For more on heapdump, see the following StrongLoop blog post.

Let's use heapdump in our code now, so that every time a memory leak is detected, we write out a snapshot of the V8 stack to disk:

memwatch.on('leak', function(info) {
 var file = '/tmp/myapp-' + + '-' + + '.heapsnapshot';
 heapdump.writeSnapshot(file, function(err){
   if (err) console.error(err);
   else console.error('Wrote snapshot: ' + file);

Run our test again, and you should notice some '.heapsnapshot' files created in '/tmp'. Now in Chrome, launch DevTools (alt-cmd-i on Mac), hit the 'Profiles' tab and hit 'Load' to load in our snapshots.

We can see clearly now that it's our 'leakyfunc()' that is at fault:

DevTools heapdump - memory leaks

DevTools heapdump

Also note that you can compare two heapdumps. This makes it easier still to find leaks between two points in time:

heapdump comparison

Comparing Snapshots


For a great overview of memory profiling in DevTools, see Taming The Unicorn: Easing JavaScript Memory Profiling In Chrome DevTools.

Turbo Test Runner

We have added a small patch to Turbo - FeedHenry's test tool - with the above technique. This allows you to write memory focused unit tests that will alert you and do heapdumps if there are memory leaks. See Turbo for more details.

Concluding observations

The above outlines one method of 'self detecting' memory leaks in node and these are my concluding observations:

  • heapdump has some caveats about snapshot size, etc.
    Read the fine print carefully. It's also CPU intensive to take a snapshot.
  • There are other ways of generating snapshots with heapdump. Pick which ever way suits your application best
    e.g. sending sigusr2 to the process, etc. This is also possible with memwatch-sigusr2.
  • Consider where and when you enable memwatch/heapdump.
    Only enable in testing and not in production. Also consider how many heapdumps to write out before possibly bailing out of the process. Again, do whatever best suits your application.
  • Consider the other ways of detecting memory growth from within your application
    i.e. monitoring the size of process.memoryUsage().rss as an alternative to memwatch.
  • When a memory leak is detected, you should also make sure it gets picked up by your monitoring and alerting tools so humans are told about it.
  • Beware of false positives: short memory spikes can appear as leaks to memwatch.
    If your app suddenly gets busy and uses a big chunk of memory which it takes a while to process, this processing time can span multiple garbage collections and memwatch will report a leak. However, there may be nothing wrong here per se. When your app is done processing, the memory usage should settle down again. What you're really looking for is persistent reporting of memory leaks. One off 'blips' may actually be ok.
  • Memwatch appears to only work with node 0.10.x.
    There is an active branch with node 0.12.x (and presumaby io.js) support here: memwatch.
  •  The gist for source code referred to in this article can be found here.


Having trouble with detecting memory leaks in node.js or want to know more on self detection of memory leaks?

You can tweet me here and connect with me on LinkedIn.

If you'd like to know more about how nearForm can help you, contact us  here or on any of the communication methods below.

Want to work for nearForm? We’re hiring.


Twitter @nearform

Phone +353-1-514 3545

Check out nearForm at


By: Damian Beresford

Damian is a software architect here at nearForm, with an interest in all things Node.js, Docker, microservices, mobile and enterprise. Damian has over 20 years’ experience with all stages of software development, across many technologies and platforms. He is passionate about software development and how next generation mobile and cloud are transforming the enterprise.
  • Shubhra Kar

    Great blog post. As a follow up, folks should be looking at the Garbage collection within V8 for understanding how heap dump results map to the managed memory segments in Node. Here is a link :

  • simon

    Looks like memwatch is broken, last commit was from 2013 and doesn’t work on node 0.12

    • benxamin

      Marco Minetti has been patching it.

      His fork runs on 0.12 (and Heroku).

      • Kelly Miyashiro

        Your link to the 0.12 branch is just a link to the original npm module.

        `memwatch.setup()` is not a method.

    • Vlad Miller

      Also try memwatch-next, seems they’re the ones who has the latest commit to memwatch fork at this time :D

      • simon

        Ok thanks Vlad I will check it out

  • Chaff

    I’d be interested in your unit test integration of this approach and how we could repurpose it to detecting memory leaks during continuous integration of client-side apps running in V8. Have you/can you publish your setup and a unit test example on GitHub?

  • Toby

    The IBM SDK for Node.js which is community node with support for IBM’s free tooling, ships with the Health Center monitoring agent npm pre installed. This gives you live GC monitoring, CPU usage and method profiling via the Health Center client and available from the eclipse marketplace We are looking at making this available outside of the IBM SDK for Node.js as this is extremely useful for detecting memory leaks and performance problems.

  • Kyle Davis

    In the article you have a line, ‘memwatch.setup();’ – it throws an error for me and it is missing in the gist. Is that a leftover from a previous version of memwatch?

  • Joao Paulo Aires Borras

    Hi, I am trying to use the code as is to learn about how to tackle memory leak problems in my own application but when I run the curl command to cause memory leak, the memwatch module gives the following output:


    Uncaught Error: attempt to end() a HeapDiff that was already ended

    { start: Sun Aug 09 2015 22:22:47 GMT+0900 (JST),

    end: Sun Aug 09 2015 22:22:48 GMT+0900 (JST),

    growth: 1805272,

    reason: ‘heap growth over 5 consecutive GCs (1s) – -2147483648 bytes/hr’ }


    And I never get the detailed information that is in this article.

    Is there anything that I have to do besides what is in the article?

    Thank you,
    Joao Paulo

  • Cory Robinson

    **** PLEASE UPDATE THIS BLOG/POST TO REFERENCE **** The current version `memwatch` is broken on current versions on Node.js and no longer maintained — install `memwatch-next`