Scaling is an important aspect of development, specifically web development as when a web application grows, its user base grows and the requests and traffic it receives also increase. It is thus essential to ensure your web application can handle the increased load without negatively affecting response time thereby impacting user experience. This article will provide an introduction to steps and strategies developers can take to scale Nodejs applications to meet the demands of an increased user base, number of requests or traffic, and by extension applications built using other technologies, languages, and frameworks.
This is referred to as scaling up and is one of the simplest and easiest to implement methods of scaling and simply involves increasing the resources available to a server or increasing the hardware of a server. These resources can include CPU, memory, and storage. It is quite easy to do as most cloud providers allow users to vertical scale their servers with a few clicks of a button. It is important to note that there are limitations and hardware constraints to the amount of resources that can be increased on a single server.
This is referred to as scaling out and involves increasing the number of servers responsible for hosting an application. Requests from users are then distributed across multiple servers ensuring that no single server is overwhelmed. It is a little bit more complex than vertical scaling as this method involves the use of a load balancer to distribute the load.
This method is often associated with horizontal scaling and involves setting up a server that distributes the load or incoming requests among a group of servers. There are several methods or algorithms load balancers use to distribute load.
Round Robin: This is the simplest and most commonly used method. Here requests are distributed across various servers in a cyclical or rotated manner.
Least Connections: In this method, requests are routed to the server with the least number of active connections.
Weighted Round Robin: In this method, requests are routed to servers based on weights. Servers with higher weights receive more requests than others. This is especially important when one of the servers has more resources than other servers.
Nginx is a popular web server that is often used for load balancing though it has numerous other applications.
Database caching is a method used to reduce the number of queries sent to a database thereby increasing performance and scalability. It is used to store frequently accessed in temporary memory. This reduces the number of queries a server makes to a database i.e. the server queries the database cache instead.
Redis and Memcached are popular caching solutions for Nodejs.
Optimizing the queries made by web servers to a database is also a good way of improving the ability of an application to scale. There are several ways database queries can be optimized:
Reducing the number of database queries made for each request.
Data indexing: This is more suitable for web applications where read queries vastly outnumber write queries as even though database indexing improves read queries, it increases the time required for write queries to complete.
Making use of database read replicas: Here other databases are added. These databases contain snapshots of the main database and read requests are distributed among the various read replicas. The main database is usually the only database that receives write requests to maintain consistency.
Appropriate use of PATCH and PUT requests: A lot of developers believe both PATCH and PUT requests are the same. However, this is not true. While PUT requests are used to modify an entire resource, PATCH requests are used to partially modify a resource, and thus PATCH requests have smaller payloads.
Reducing API payload: Most API payloads are quite small, however, there are times when the user needs to SELECT all resources that match certain criteria and these can result in thousands to millions of responses. In such cases, it is often more performant to compress or reduce the size of the payload.
Using a microservice architecture involves breaking an application into smaller and more manageable components or services that can be handled independently. These services often focus on specific functionality e.g. in a social media platform, there can be individual services for authentication, user profiles, posting, messaging, handling user feeds, comments, etc. This ensures that even if one of these services fails or encounters a downtime, the remaining services work well. It also allows for deploying individual services in a way that does not affect other services, thereby improving overall scalability. It is important to note that this method also increases the complexities involved with managing the application as a whole.
Nodejs uses an event-driven, non-blocking I/O model makes it well-suited for building scalable asynchronous applications. Using techniques such as callbacks, Promises, and async/await allows developers to develop asynchronous code, non-blocking in Nodejs.
Stateless authentication also known as token-based authentication is an authentication method where the server does not store details of a user's session. The server instead generates a unique token for a client. The client subsequently uses that token to authenticate itself and the server validates the token upon each request.
This process reduces the workload on a server as the server does not need to store the session data which can lead to increased memory and processing overhead.
There are various methods of scaling a database and no one method is better than the other and often a mix of more than one of these methods is required to scale an application properly. It is the job of the developers to determine the best method or methods and implement them appropriately.