258

In what cases should one prefer to use Node.js only as a server in real deployment?

When one does not want to use Node.js only, what plays better with Node.js? Apache or Nginx?

7cows
  • 4,974
  • 6
  • 25
  • 30

6 Answers6

236

There are several good reasons to stick another webserver in front of Node.js:

  • Not having to worry about privileges/setuid for the Node.js process. Only root can bind to port 80 typically. If you let nginx/Apache worry about starting as root, binding to port 80, and then relinquishing its root privileges, it means your Node app doesn't have to worry about it.
  • Serving static files like images, css, js, and html. Node may be less efficient compared to using a proper static file web server (Node may also be faster in select scenarios, but this is unlikely to be the norm). On top of files serving more efficiently, you won't have to worry about handling eTags or cache control headers the way you would if you were servings things out of Node. Some frameworks may handle this for you, but you would want to be sure. Regardless, still probably slower.
  • As Matt Sergeant mentioned in his answer, you can more easily display meaningful error pages or fall back onto a static site if your node service crashes. Otherwise users may just get a timed out connection.
  • Running another web server in front of Node may help to mitigate security flaws and DoS attacks against Node. For a real-world example, CVE-2013-4450 is prevented by running something like Nginx in front of Node.

I'll caveat the second bullet point by saying you should probably be serving your static files via a CDN, or from behind a caching server like Varnish. If you're doing this it doesn't really matter if the origin is Node or Nginx or Apache.

Caveat with nginx specifically: if you're using websockets, make sure to use a recent version of nginx (>= 1.3.13), since it only just added support for upgrading a connection to use websockets.

pauljz
  • 10,803
  • 4
  • 28
  • 33
  • 12
    `express.static` will handle ETags and cache-control headers just fine. – robertklep May 27 '13 at 10:13
  • Indeed it will, but that assumes you're using Express. It's also slower than a static server, and you would need to confirm that whatever framework you're using (if it's not Express) will do this for you. – pauljz May 27 '13 at 10:15
  • I'm not saying it's faster, I'm saying it's not something to have to worry about if one wants to serve static content with Node :) – robertklep May 27 '13 at 10:16
  • Yeah, fair point there. Edited my answer to mention this. I think it's worth pointing out the header issue as if you're just using the built in `http.createServer` with `fs.readFile`, you're not getting *any* of that kind of efficiency. – pauljz May 27 '13 at 10:17
  • Are there any reasons to prefer Nginx over Apache or vice versa (when using them with Node.js) from something other than performance point of view? I will not have popular enough sites any time soon to be worrying about the performance differences. – 7cows May 27 '13 at 10:46
  • I'd say go with what you know. I prefer nginx and find it to be more efficient with resources, and easier to configure, but if you know Apache, might as well use it. You can always swap it out later too if you run into issues (performance or otherwise) down the road. – pauljz May 27 '13 at 10:47
  • 22
    Node isn't that good huh? http://centminmod.com/siegebenchmarks/2013/020313/index.html, http://zgadzaj.com/benchmarking-nodejs-basic-performance-tests-against-apache-php – el vis May 27 '13 at 10:48
  • 5
    pauljz, do you have benchmarks to back up slower? the articles @pawlakpp pointed out seem to say Node.js is much faster under load. – Samuel Neff May 27 '13 at 15:48
  • @SamuelNeff there are circumstances when Node could be faster than a generic fileserver like nginx, but it's not the norm, nor the conventional wisdom. Honestly the best choice and what most folks should be doing is serving static files from a CDN or something like Varnish, in which case node vs nginx is irrelevant. (I'd actually still be pretty interested to see what the actual code they're using to serve is in that benchmark though.) – pauljz May 28 '13 at 11:04
  • 5
    There's some related discussion here: http://stackoverflow.com/questions/9967887/node-js-itself-or-nginx-frontend-for-serving-static-files with some additional perspectives. The benchmarks there (since you asked for additional benchmarks) show node.js/express, even clustered, underperforming noticeably. My feeling is it's best to keep static file serving and request handling out of the node event loop entirely, save those cycles for the work that needs to happen in Node. But honestly, if you serve static stuff out of Node, you'll be fine too. It's not a big deal. – pauljz May 28 '13 at 11:20
  • 4
    Benchmarks are useful and provide meaningful information, however the difference is not large enough in most applications to warrant concern over these numbers. Having Nginx/Apache in front of Node might be better, but in most situations it is simply overkill and adds unnecessary complexity. It all depends on your needs. My opinion is to make it work using NodeJS only and if the throughput is not to your liking, then consider adding a webserver in front. – Nepoxx Sep 26 '14 at 13:56
  • 4
    It should be noted that if you're using just node directly, you can still bind to reserved ports such as `:80` without running node as root by simply using authbind: https://thomashunter.name/blog/using-authbind-with-node-js/ – wyqydsyq Dec 04 '14 at 03:11
  • 1
    With the most recent node, aws shield, and aws cloudfront, is there any benefit to sticking another webserver in front of node? With an aws stack, does nginx/apache even buy you any caching/security benefit? – David Jan 23 '17 at 18:31
  • `Only root can bind to port 80 typically` what does it actually mean? Could you please elaborate further? – Vishnu Sureshkumar May 05 '17 at 11:29
  • 2
    Wishnu It means that ports under a certain port number (1024?) are reserved usually for well known applications (such as a webserver on port 80, telnet on port 25, secure email on port 443, etc). Your process needs to be run as root to be able to bind the socket on that port. Above 1024 anyone can as long as it is unused. – Gerard ONeill Oct 24 '17 at 21:37
86

Just to add one more reason to pauljz's answer, I use a front end server so that it can serve up 502 error pages when I'm restarting the backend server or it crashes for some reason. This allows your users to never get an error about unable to establish a connection.

Matt Sergeant
  • 2,762
  • 16
  • 12
35

It is my belief that using Node to serve static files is fine in all circumstances as long as you know what you're doing. It is certainly a new paradigm to use the application server to serve static files as so many (every?) competing technologies (PHP, Ruby, Python, etc) require a web server like HTTPD or Nginx in front of the application server(s).

Every objective reason I have ever read against serving static files with Node revolves around the idea of using what you know best or using what is perceived as better-tested / more stable. These are very valid reasons practically speaking, but have little purely technical relevance.

Unless you find a feature that is possible with a classic web server that is not possible with Node (and I doubt you will), choose what you know best or what you'd prefer to work with as either approach is fine.

As for Nginx vs Apache -- they will "play" with Node the same. You should compare them without regard to Node.

  • 2
    Good perspective on technical comparisons in general: "Every objective reason I have ever read against serving static files with Node revolves around the idea of using what you know best or using what is perceived as better-tested / more stable. These are very valid reasons practically speaking, but have little purely technical relevance." Too many comparisons these days are biased and based upon the baggage of experience and comfort-level on inferior but time-tested technologies. – Sunny Jul 09 '15 at 04:04
  • Yes but they're really /subjective/ reasons. A great example of an objective reason would be a benchmark - most of which I found indicate nginx > nodejs (though I really should do my own ....) – Nick Nov 20 '15 at 01:22
  • @Nick You're absolutely right. And there are a few out there though I'm not an expert in scientific bench-marking so I'll let people search the web for that. What I will say though is I think there is a benefit to the simplicity of using one server instead of two. There's just less potential for something to go wrong. On the other hand, Nginx usually has a package on every Unix-like system with good configuration whereas with Node you need to figure out integration with `systemd`, `pm2`, etc. So there are pluses and minuses and the user should pick their poison, so to speak. –  Nov 20 '15 at 02:38
  • I thought it was the opposite -- node would do better under load (perhaps not in pure unloaded speed) because it doesn't have to handoff a process serving up a file per request, but rather can push data when either the local disk or the remote client are ready on the same thread that all the other thousands of clients are on. This of course breaks down when you have multi processors.. Unless node knows how to use them now. Or webservers may use cooperative multitasking to server up static pages now.. – Gerard ONeill Oct 24 '17 at 21:49
15

Using Node.js only

Node.js can do all the tasks of a web server: serve static files, respond to an API call, run server on HTTPS... There are also a lot of packages that provide extra functionalities like logging the request, compress the response, set cookies, prevent XSS attacks... Lack of functionalities isn't likely a reason for using another Webserver (Apache/Nginx/etc..) to complete Node.js. In other words, for a simple application that does not need to scale, you don't need to add an extra layer to Node.js, it just complicates the problem.

Using Node.js with another webserver

Each web server has its own advantages. For example, Apache allows additional configuration per-directory via the .htaccess file. Nginx is known for its performance when it comes to serving static files or acting as an reverse proxy. Node.js provides a huge benefit when dealing with I/O heavy systems... Sometimes, we need to combine the forces of different web servers to satisfy the system's requirements.

Example: For an enterprise-level application that might scale up in the future, set up Nginx as a reverse proxy before Node.js application has some advantages :

  • Nginx can act as a load balancer to dispatch traffic to your NodeJS instances if you have more than 1.
  • Nginx can handle HTTPS, caching, and compression for you. Encryption and compression are heavily computed operations that NodeJS is not good at. So using Nginx will give you better performance.
  • Nginx will serve static content, which reduces the load of Node.js.
  • Separation of concerns: Nginx takes care of all the "configuration" part, and Node.js focus on the application logic.
Đăng Khoa Đinh
  • 5,038
  • 3
  • 15
  • 33
8

Placing NGINX in front of Node helps better handle high connection volumes. NGINX offers (to name a few) caching, load balancing, rate limiting (using the leaky bucket algorithm) and can help mitigate attacks if paired with a banning service like Fail2ban.

As for production applications, you can run your application server behind NGINX as reverse proxy, coupled with a caching server like Redis- all of which can be situated behind a content delivery network as another line of defense from exposing your ipv4/ipv6.

Sean
  • 171
  • 1
  • 2
5

An extra: It is important also if you need a Reverse Proxy, for example to execute a Websocket Server on the same port, or maybe mix some techonlogies (reply with NodeJS some requests and with PHP some others or whatever)

Enrique
  • 4,693
  • 5
  • 51
  • 71