6 small tips to prepare your NodeJS for high loads
Developing on NodeJS as a hobby is a pleasure, but when it comes to production for many users, there are a couple of things that you should know to avoid a long response and glitches.
As part of our work at MyHeritage, we developed the doppelgänger service for Eurovision 2019, with which, by uploading a selfie, you can find out which of the contestants are most similar to you.
In addition to the logic of face recognition, the application had an extremely clear requirement: it had to serve tens of thousands of simultaneous users, because millions of people around the world watch Eurovision.
Very quickly, we realized that the load balancer in front of the application configured with Auto Scaling is not enough for fault tolerance. The following helped us a lot:
- Hope for the best, but get ready for the worst: measure how many concurrent users will be able to serve your application in time X (in one instance). For example, in our case, testing showed that we can serve 200 concurrent users in each EC2 instance for 10 seconds, so when we found out that we should serve 10,000 concurrent users, we just had to prepare 50 servers for the balancer. For the test, we used an excellent tool called JMeter .
And this tutorial greatly helped in preparing for the measurements.
- Avoid locks: blocking operations are (sort of
fs.readSync) tempting because the code looks cleaner, but they literally kill performance. Use
awaitoperations instead , because during asynchronous operation the CPU will be available for other tasks (see Event Loop ).
const res = fs.readSync('file.txt');
const res = await fs.readAsync('file.txt');
- Increase the memory limit:
Nodethe default setting is 1 GB. If the server has access to, say, 4 GB specifically for your application, you will have to manually set the maximum memory limit using the CLI with the following flag: Example:
node --max-old-space-size=4096 server.js
- Make sure that you use all the processor cores: by default it
Nodeworks in the same thread. If you have not specifically configured a configuration that would run several threads, save money by choosing a server with 1 core.
- Reduce the number of calls to the application: configure forced HTTPS and all redirects as high as possible (for example, at the proxy level). This will allow the application not to be distracted by superfluous, and, therefore, be more accessible for requests that are really important.
- Error handling: use logging, for example Logz.io/AWS CloudWatch to track errors that can lead to application failure. DO NOT report services like Slack about everything, because messages usually go in bulk and can easily clog a channel. We used an excellent library called Winston for logging in NodeJS.
In our case, these tips led to a tenfold improvement in productivity and helped to keep the production environment clean even when you had to serve thousands of users at the same time.
Thank you for reading.