JavaScript
Article
By Craig Buckler

5 Easy Performance Tweaks for Node.js Express

By Craig Buckler

Node.js has revolutionized web development and the Express framework must share much of the credit. Express may not be the fastest or most advanced server option, but it’s almost certainly the most-used with more than 3 million downloads per month.

If you do nothing, Node.js and Express run blazingly fast. However, there are a number of simple ways to make Express 4.x run even faster…

1. Switch to Production Mode

Express can run in several modes. By default, it presumes development mode which provides exception stack traces and other logging tasks. There is also a debugging mode which logs messages to the console, e.g.

DEBUG=express:* node ./app.js

On your live server, you can noticeably improve performance by switching to production mode. This is achieved by setting the NODE_ENV environment variable to production. It can be set in the current session on Windows prior to launching your Express application:

set NODE_ENV=production

or Mac/Linux:

export NODE_ENV=production

Linux users can also set NODE_ENV in a single line when launching:

NODE_ENV=production node ./app.js

Ideally, you should configure your environment by adding export NODE_ENV=production to your ~/.bash_profile or appropriate start-up script.

2. Enable GZIP

Express 4.x provides minimal functionality which can be enhanced with middleware. One of the less obvious missing features is GZIP compression which shrinks the HTTP payload so it can be expanded by the browser on receipt. To add GZIP, install the compression module using npm:

npm install compression --save

(Depending on your setup, you may need to use sudo on Mac/Linux — there are various ways to fix that.)

In your main application launch file, include the compression module:

var compression = require('compression');

then mount it as the first middleware function (prior to other Express .use methods):

// GZIP all assets
app.use(compression());

3. Remove Unnecessary Middleware

If you generated a pre-built application using Express Generator or a similar process, remove any middleware modules you’re not using.

For example, if you’re not using cookies you could remove the cookie-parser module or implement a simpler alternative using req.cookies and res.cookie.

It may be possible to remove certain processes such as debugging output in production mode, e.g.

if (app.get('env') !== 'production') {
  // debugging middleware in development only
  app.use(debuggerModule);
}

That said, it’s possibly best to keep serve-favicon. Browsers request favicon.ico files frequently and the module improves caching.

4. Consider a Simpler Template Engine

Jade is the default template engine for many Express installations and it’s a great choice. However, if you’re happy writing your own HTML and just need basic interpolation and evaluation, consider a lightweight alternative such as doT which can be added as Express middleware using the express-dot-engine module.

Alternatively, you can bypass the template engine for simpler responses, e.g.

app.get('/hello', function (req, res) {
  res.write('Hello!');
  res.end();
});

Which ever template engine you use, always ensure the view cache is enabled:

app.set('view cache', true);

5. Remember to Cache!

Unlike most server-based applications, Node.js apps run permanently. You can therefore set frequently-used variables such as database connection objects once and re-use them during every request for every user.

The concept can be extended as necessary. In general, the more high-use items you can cache the better performance will be. For example, presume your Express-based CMS application presented links to your five latest articles on the home page. That list could be generated and stored in a variable and only updated when a new article is posted.

Bonus Quick Tips

Want a few more?…

  • Consider using nginx to serve static content and lighten the load on Node.js and Express.
  • Use a build tool such as Gulp to minify and concatenate your HTML templates, CSS and JavaScript files.
  • Limit the use of session variables. User session data is normally stored in memory which can lead to performance issues as usage grows. Consider using an ID only then fetch user information from a database during the request.
  • Increase the maximum number of HTTP sockets from five to a higher number, e.g.
    
      // use http/https as necessary
      http.globalAgent.maxSockets = 50;
    
  • Where possible, call sequences of blocking operations in parallel rather than in sequence.
  • Avoid using synchronous blocking calls in everything but application initialization.
  • Always be conscious that code running for one user is blocking code running for every other user.

Do you have further performance tips for Node.js or Express? I’d be glad to hear them in the comments.

  • Chris Hickman

    A minor clarification: With Node 0.12, the limitation of maxSockets=5 was removed (and set to infinite). So manually overriding maxSockets for the http(s) agent is only necessary for Node 0.10 and older. Also, not sure how configuring maxSockets helps with performance per se, since this parameter controls the size of the connection pool for outbound requests, where the cache key is destination IP address. So configuring maxSockets might help if you are trying to make many concurrent connections to the same host from your Node.js server, but won’t necessarily make your operations more performant.

    • Craig Buckler

      Thanks for the clarification, Chris.

  • PaulTopping

    Regarding “Unlike most server-based applications, Node.js apps run permanently.” Are you saying that in other server frameworks, the app only runs to process a single request and, therefore, can’t save any state? If so, I suggest expanding these words a little to make it easy on newbies. After all, nothing runs permanently (ie, forever).

    Otherwise, great post! I am going to bookmark it for use as a checklist when I create my first Express site.

    • Craig Buckler

      Thanks Paul. I actually meant that Node apps are continually “on”. While they’re running, they can handle web requests or perform background tasks. This is different to most server-side languages such as PHP or Ruby which initialise a new process every time an HTTP request is made. Therefore, in Node you can initiate variables such as a database connection or cached list of posts and re-use them during every request.

  • Guy Ellis

    Your 5th point about caching is important. I created (with others) an Npmjs module called multi-level-cache that manages local and remote caches for node. The idea is that it looks in its in-memory local cache for the data (which might have expired) and then at a remote cache (which also might have expired) before looking at the DB. You can create an efficient caching hierarchy with this type of architecture to speed up your apps.

  • mManishTrivedi

    Great article!

    I want to know how can I store my socket-connection information + some other stuff with Good way ?? (I am talking about your third point of bonus tips)
    Currently, I am using memory to store this stuff. Any better way than memory and how can I test memory issue ?? I think strongloop providing library for this. Any feedback from your side ??

  • express-session calls JSON.stringify() on every session object and computes a CRC off of that, for every request, as a way to determine whether a session changed. That’s pretty heavy right there.

  • Nasser Alminji

    “Always be conscious that code running for one user is blocking code running for every other user.”

    Simple and conscise. Well done.

  • justin

    Utilieze Redis with your ORM such as Sequelize. I use npm redis-sequelize-cache https://www.npmjs.com/package/sequelize-redis-cache/

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.