Web Api Performance
2-Response Time Optimization
Previously we talked about Restful Design, what it is and the importance for our API to follow its standards and conventions to create a fast, reliable and scalable RESTFUL API.
Now let’s dive into the second step of optimizing web API performance: Response Time Optimization.
Response time is a critical factor in delivering a responsive and efficient API experience to users. Here’s how you can optimize the response time of your API:
Minimize Network Latency:
a- ) Choose data centers or hosting locations that are geographically close to your target audience.
The logics of the real world rules are exactly the same in the logic of the programming world, because going to your kitchen to get a new bottle of coca cola will take less time than picking up that bottle from a supermarket.
Here both supermarket and kitchen represent your data hosting location.
It means that an app that will be only use in Ivory Coast with its hosting location in china will not have the same response speed as if its server(s) was in the same country.
Use case with the image bellow as illustration
Here the bubbles with centered letters represent the servers (hosting location) and the square represents the application. Regardless of the quality and performance of the servers, you should choose the closest server possible.
so servers (E, G, F, H ) are a better choice.
I mentioned server performance and quality because distance is not the only parameter to consider. Choosing a bad server just because it’s the closest is not a good thing to do when you want your API to work properly.
What you need to consider is the geographical distance and the server capacity.
Optimize Database Queries:
a- ) Use efficient database queries by selecting only the necessary columns and rows of data.
Selecting more fields than necessary will increase the response time and the volume of your response
for example, an array of one thousand items like this 👇🏾
const itemArray :{username:string, email:string, pwd: string}=[
{
username:"John doe",
email:"doe@mailio.az",
pwd: "skjdubss"
},
....99 other items
]
will have a lower volume and response time than a query that needs to send a response like this 👇🏾
const itemArray :{
username:string,
email:string,
pwd: string,
avatar_url:string,
posts: Post[],
documents: Documents[]
}=[
{
username:"John doe",
email:"doe@mailio.az",
pwd: "skjdubss",
avatar_url:string,
posts: [{...postsList}],
documents: [{...documentList}]
},
....99 other items
]
So make sure you really need all the items you are asking your database to send via your queries.
b- ) Avoid N+1 query problems by utilizing eager loading or database joins
N+1 query means querying your database more than once to get the final answer you need.
Suppose you want to fetch a user by his id
and in addition you want all his posts, by using the N+1 query method, you will firstly find and fetch the user by his id .
Fetching route example : https://api-route/users/426ghh-5266t-RZGUZHZ
Then fetch the posts table to get all the user posts
Fetching route example : https://api-route/posts/egZHZ-12tgeg-6272v-jzhz
Performing two queries will take longer to get the data we need, which will cause a performance hit at the client level in addition to overloading the server with unnecessary queries.
So do your best to get the data you need in a single query. (utilizing eager loading or database joins)
— What is eager loading :
Eager loading is a performance enhancement strategy employed in software development, often within the realm of Object-Relational Mapping (ORM) frameworks.
In eager loading, when you retrieve data from a database, you fetch not only the main object you’re interested in but also related objects or data that are commonly accessed together. This reduces the number of database queries and, consequently, improves performance by minimizing the “N+1 query problem.”
For instance, let’s take a blog application as an example. In the absence of eager loading, if you retrieve a list of blog posts and then separately retrieve comments for each post, you would execute one query for obtaining the blog posts and N additional queries to fetch comments for each post (with N representing the number of posts). This approach can result in a substantial performance overhead.
In contrast, when you implement eager loading, you can direct your ORM to retrieve both the blog posts and their corresponding comments in a single database query, typically accomplished through SQL JOIN operations. This streamlined approach optimizes data retrieval by reducing the number of database queries, ultimately enhancing the efficiency of your application.
Eager loading proves especially beneficial in situations where you anticipate that specific related data will frequently be accessed together, thereby reducing the time and computational resources required to load and display this data within your application.
— What is database joins :
Database joins are operations used in relational databases to combine data from two or more tables based on a related column between them. They are fundamental for retrieving and working with data distributed across multiple tables in a structured and efficient manner.
Caching
Optimizing response time through caching is a crucial strategy for improving the performance and responsiveness of web APIs and applications. Caching involves the temporary storage of frequently requested data or responses, so that subsequent requests for the same data can be serviced quickly without the need to regenerate the response from the source.
a- ) Client-Side Caching:
Client-side caching involves storing data or responses on the user’s device, typically in the web browser’s cache, commonly used for static assets like images, stylesheets, and JavaScript files and controlled through HTTP caching headers (e.g., Cache-Control
, Expires
, ETag
) sent by the server in response headers.
b- ) Server-Side Caching:
Server-side caching involves storing data or responses on the server or an intermediary server (like a proxy or CDN), especially for dynamic content or data that doesn’t change frequently. It helps reduce the load on the application server and database.
Compressing Responses
Response compression is a performance optimization technique used to reduce the size of data transferred over the network. Smaller responses result in faster load times and better user experience, especially for users with limited bandwidth or on slower connections.
Common Compression Algorithms are :
— GZIP: Widely used, and works well for compressing text-based content such as HTML, CSS, JavaScript, and JSON. Most modern web servers and clients support GZIP compression.
— Brotli: A new compression algorithm developed by Google. It offers better compression rates than GZIP, which makes it more efficient for textual content. However, Brotli support may not be as widespread as GZIP.
Applying all these methods will help us to improve the performance of our Apis, which means better client-side application quality and better user experience.
Next time we will talk about “network efficiency” but in the meantime, I hope you find this article useful and feel free to leave your opinions in the comments.
Follow me there :
linkedin.com/in/laetitia-christelle-ouelle-89373121b/
twitter.com/OuelleLaetitia
Happy coding ! 😏