Most developers will be able to create solutions to meet the functional requirements of an application. However, to make it scalable where the application continues to perform well even with extremely high data volumes or user traffic requires a more detailed understanding of how things operate across various layers of software and hardwires.
There are lots of small and big factors which affect the scalability and performance of a website, ranging from coding practices, data model design, database optimization, communication between different layers of the software, server software configuration and many more.
Following are some of the important development best practices.
1. Design data model diligently
Ensure that extra care is taken while designing the data model. Database operations are the biggest resource consumers and a poorly designed data model can severely handicap the scalability and performance of a website. If the database server provides you a feature, go ahead and use it rather than reinventing the wheel. Database servers have been designed and have evolved precisely to handle data in the most efficient way. So do not hesitate to add relationships and constraints where they logically should be. Defining relationships and constraints comprehensively facilitate faster processing by the database server. Ensure that every database table has a primary key, so that it is properly indexed. If there is a column which is expected to be unique and serves as a foreign key to other dependent tables then that column should be made the primary key. Consider creating customized indexes to aid more time consuming queries.
2. Use stored procedures
Wherever possible use stored procedures to implement database level business rules or perform other database operations. Compiled stored procedures are much faster and provide a separation between the presentation of data and the database level business rules. In addition, usages of stored procedures safeguard the website against SQL injection attacks.
3. Segregate database and its access
Most of the large scale websites use database read operations much more heavily than database write operations. Database reading operations are much faster than the write operations. Consider creating a master and a slave database where all the write operations are carried out in the master database and all the read operations are carried out from the slave database. Setting the database access privileges properly will let the database server perform much better. Of course, the two databases can be synchronized but that process can keep running in the background. Many database servers provide mirroring feature, which can automate this process. If having two databases is not possible, consider using a single database with two different access level, one only for reading and other for writing. Having the right level of access control for the databases will automatically increase the security level.
4. Use server cache
Use caching for commonly used details and static data. This is true for data stored in the database as well as program variables, especially string variable. Caching can be enabled for data contained in the database using the available frameworks, e.g. using EnableCaching for the SqlDataSource in ASP.Net / C#. Complex database queries can be simplified and made faster by eliminating joins with tables containing static data. Program variables, e.g. text / strings, which are not expected to change, should be stored as static variables in a reusable components or library.
5. Handle string concatenation efficiently
Ensure that string operations are performed as much as possible in the memory and not by creating unnecessary objects. Use classes like StringBuilder (in C#) or StringBuffer (in Java) to concatenate the strings. Using the ‘+’ operator to concatenate the strings may appear very simple, but it has a significant performance overhead. In this approach the Framework copies both the existing and new values in the memory, deletes the existing string, and reads data in the new string, making the operation very expensive. And when the operations are carried out on a large scale, its effect gets magnified.
6. Avoid round trips to the server
Try to avoid round trips to the server and minimize the data transfer, bandwidth usage and load on it. If possible, create Ajax based solutions. This will avoid full page refresh and only update the portion of the page which needs to be changed. Besides providing the other benefits this will improve the user experience as well.
Use client-side scripts wherever it can be done without compromising the security. Client-side validations can provide quick response to the user for data input without increasing the load on the server.
7. Use session variables prudently
Avoid storing a lot of data in session variables. In case of high number of concurrent users this can consume a significant amount of server resources for session management, and also make the front-end heavy for the user. Data stored in session variables can consume resources even long after the user closes the browser window. Some libraries which store session details on the server will pose significant limitation for load balancing in case of a load balanced cluster of servers. Disable session state management, if session variables are not used in a particular web page or application.
8. Use server transfer
If there are pages which are not required to be directly accessed by the users and are linked to a workflow, e.g. search results page, then use server’s internal transfer mechanism using methods like Server.Transfer (in ASP.Net) or Request.Forward (In J2EE). This avoids unnecessary client-side redirection. However, for pages which require authentication during redirection, client-side redirection, e.g. using Response.Redirect, which is treated as a fresh request, should be used.
9. Avoid use of server controls where dynamic behaviour is not needed
Server controls should be used only for the elements on the web pages which are expected to have dynamic rendering of content. For things which can be easily achieved using the standard text or HTML elements, server controls should be avoided. Even if server controls are needed use of deeply nested controls should be avoided, as they come at a reasonable performance cost.
10. Use exception handling judiciously
Occurrence of exceptions is a significant performance deterrent, and more so if it is in a heavily used website. Programming should be defensive in nature, i.e. analyze the possibility and nature of exceptions which can occur in a particular section of code and preempt them. E.g. checking if the values are numeric before performing any mathematical operation.
11. Use paging optimally
Retrieving and transferring unnecessary data simply increase CPU utilization, memory consumption and bandwidth usage. More data to render and heavier load on the server leads to slower response time and poor user experience. Retrieve and render the content which is relevant. Decide the page size optimally. If possible, implement paging logic in the database to optimize the data set to be handled.
12. Release resources after using
Ensure that the resources like database connections, files, messages, etc. are closed and / or disposed. Resources which are not released will keep on hanging in the server and in some cases could cause unavailability of some resources and memory leaks.
13. Use precompiled pages
Wherever possible precompile the web pages before deploying on the production server. This will avoid the compilation of the pages on receiving the request and will ensure faster response to all the users at all times. Deploying the pages in precompiled format will also safeguard the code against several types of malicious attacks, e.g. IFrame attacks.