While writing complex applications, we unknowingly use code that can downgrade the performance or make your application vulnerable to security threats. Today, I am going to share with you a few tips and tricks that you can use to increase your application's performance and make it more secure.
Use cluster to maximize performance
Node.js runs over a single CPU in default mode. This is a major issue as your app will not be able to properly utilize the hardware. To overcome this you can use the node's cluster module which will help you spawn a process for each core with a few lines of code. You can even use PM2 for this which makes clustering your application even more simple.
Increasing the Threadpool size
Libuv is an open-source library that handles the thread-pool which is used by node for many asynchronous operations like file I/O. If your application is slowing down in terms of file I/O or crypto operations, you can increase the thread pool size by setting UV_THREADPOOL_SIZE env variable.
Assign anything possible to reverse proxy
Assign CPU intensive tasks like serving static files, gzipping, SSL, etc to the reverse proxy. Although you can use express middleware to do all this stuff in node itself, this will degrade the performance because of its single-threaded model which will keep the CPU busy for long periods. You should use services like nginx and HAproxy.
Audit you 3rd party packages for vulnerability
Security is one key aspect of the application. You should always make sure your code and dependencies are secure. You should use tools like npm audit or snyk to check for vulnerable dependencies. You can also use dependabot to always keep your dependencies updated.
Don't block the event loop
This is a no-brainer. Anyone who knows Javascript and Node already knows that it is a single-threaded. If the event-loop is blocked, Node.js will not be able to handle other requests causing delays for other users.
Do not use anonymous functions
You should name all the functions, closures and callbacks. This will help you easily understand what you are looking for from memory snapshots while profiling your application. Without this, debugging production issues will become very challenging as you will start to notice significant memory exhaustion by anonymous functions in memory snapshots.
Use static type checker
Static type checker will empower you to find certain problems even before your code executes. It is certainly helpful as you will get fewer surprises on the runtime of your application. It also helps when you are refactoring your application, as changing a signature of a method in one place, type-checkers will enforce you to change it in all the places. With static type checking, you can also utilize great IntelliSense support. You should check Flow or TypeScript for getting started with the static type checking.
Use Task queuing system (Background jobs)
Web applications work on request and response cycles. Ideally, this cycle should be fast, otherwise, a web server can only serve a small number of users at a time. You can use a Task queuing system for performing heavy computation tasks in the background. The export of big amounts of data, video/image processing, a report compilation are a few examples of cases where you may want to use a task queuing system. For this, I'll recommend you to check Bull or Kue package.
- Jaskaran Singh