Zoho Catalyst Cache: Elevating Node.js Application Performance
As the demand for optimized application performance continues to grow, […]
Published on March 1, 2024
As the demand for optimized application performance continues to grow, developers seek tools that can seamlessly enhance efficiency. Zoho Catalyst Cache emerges as a powerful solution, particularly for Node.js applications, offering a robust mechanism for data caching. This guide will comprehensively explore Zoho Catalyst Cache, from understanding its capabilities to practical implementation using Zoho nodejs serverless functions. We’ll create serverless functions: one endpoint without caching and another with Zoho Catalyst Cache integrated.
Understanding Zoho Catalyst Cache: A Comprehensive Guide
Zoho Catalyst Cache is a dynamic caching solution designed to boost the performance of applications by efficiently storing and retrieving frequently accessed data. It is a part of Zoho Cloud Scale Service.
Leveraging in-memory caching significantly reduces latency and accelerates data access, delivering a seamless user experience. It is based on Redis cache with Zoho’s powerful infrastructure.
Key Features
Memory Caching: Store frequently accessed data in memory for rapid retrieval.
Distributed Architecture: Ensures scalability and reliability for diverse application workloads.
Data Consistency: Offers mechanisms to maintain data integrity across the cache.
Flexible Configuration: Tailor caching strategies based on your application’s unique requirements.
Zoho cache concepts
For Zoho Cache, the two concepts are the most crucial and will be mostly used by you when developing.
Segments
Partitions known as segments play a crucial role in the Catalyst cache system. These segments act as distinct units, organizing and categorizing data for similar purposes. When you create a cache segment through the Catalyst console, it automatically generates a unique Segment ID for identification. This ID can be used to reference the segment, and you can manage its cache items either through the console or your application’s APIs.
The Catalyst console allows you to view or update cache items associated with a segment. It’s important to note that if you haven’t explicitly created a segment or specified a Segment ID for an operation using the SDKs or API, the system defaults to the automatically created default segment when caching data.
Cache Item
The in-memory item where each one essentially consists of a key-value pair within Catalyst. This pair includes a key name, serving as a unique identifier, and a corresponding value. Additionally, a cache item contains an expiration time, determining its validity in hours. By default, data in a cache item remains valid for two days, after which it is automatically removed from the cache memory. However, you have the flexibility to override this default expiration time and set it to a duration of two days or less based on your specific requirements.
Use case for segments and cache items
Let us assume you are dealing with sales data in an application. It is common to have multiple analytics and dashboards in such applications. These can be calculated on a daily, weekly, or monthly basis.
With segments, you can store the respective dashboards in their segments and hence ensure the separation of concerns. Since these calculations are heavy, if your application sees huge amounts of traffic, there can be big latency for the users and the requests might seem to end with a timeout which is a bad UX.
So, by combining segments and cache items, the same dashboard can be served to all users without recalculating it again and again.
Setting Up Zoho Catalyst Cache: A Step-by-Step Process
Prerequisites
Ensure you have the following
– A Zoho account
– Zoho catalyst cli installed globally on your machine.
– An IDE for coding.
Now, access your Zoho account and open the Catalyst Dashboard. From there, you can create your Catalyst project. You can also use your catalyst-cli for the same job.
After this, you will be redirected to the following view.
As we have discussed before, a default segment will be created in the cache section.
Let us create a new cache section for our demonstration example.
Now that everything is set up, write the following command in the terminal to initialize the catalyst project in the directory of your choice.
catalyst init
And check the function
And finally Advanced IO. We will be writing an express js app hence the option.
To use express js, move to the function’s directory and run npm install express –save to install the library.
Example 1: Without Cache
Create a new file named index.js and paste the following code inside it.
const express = require("express");
const app = express();
async function fetchUserProfile(userId) {
console.log(`Fetching user profile for user ${userId} from the database...`);
return new Promise((resolve) =>
setTimeout(() => resolve({ userId, name: "John Doe" }), 1000)
);
}
app.get("/user/:userId", async (req, res) => {
const userId = req.params.userId;
const userProfile = await fetchUserProfile(userId);
res.json(userProfile);
});
const port = 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
module.exports = app;
In this example, the /user/:userId
endpoint triggers a direct dummy database fetch without caching. Each request incurs a delay associated with querying the database.
As you can see above, the API returns responses exactly after one second. It will be the same for each request.
Example 2: With Zoho Catalyst Cache
const express = require("express");
const app = express();
const catalyst = require("zcatalyst-sdk-node");
async function fetchUserProfile(userId) {
console.log(`Fetching user profile for user ${userId} from the database...`);
return new Promise((resolve) =>
setTimeout(() => resolve({ userId, name: "John Doe" }), 1000)
);
}
app.get("/user/:userId/cache", async (req, res) => {
const catalystApp = catalyst.initialize(req, {
type: catalyst.type.advancedio,
});
const userId = req.params.userId;
// Add your segment ID.
const segment = await catalystApp.cache().segment("2603000000012124");
const cachedUserProfile = await segment.get(userId);
if (cachedUserProfile.cache_value) {
console.log(`Fetching user profile for user ${userId} from the cache...`);
const userProfile = await segment.get(userId);
res.json(userProfile);
return;
}
const userProfile = await fetchUserProfile(userId);
await segment.put(userId, userProfile.name, 2);
res.json(userProfile);
});
const port = 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
module.exports = app;
In this enhanced example, Zoho Catalyst Cache is seamlessly integrated. The fetchUserProfile
function is now wrapped in caching logic. If the user profile is not found in the cache, it is fetched from the database, stored in the cache, and then returned in the response.
For the first request, it will take the same time as the previous function but in the subsequent requests, the return data will be way faster as seen in the below screenshots. Time has been highlighted by the red rectangle.
First request
Time taken: 1316ms
2nd request.
Time taken: 326ms
You can also see the data stored from the Catalyst dashboard.
Real-World Use Cases for Zoho Catalyst Cache: Enabling Scalability and Performance
Zoho Catalyst Cache finds practical applications in diverse scenarios:
E-Commerce Platform:
Cache product information to reduce database load during high traffic, ensuring faster product page loading times.
Social Media Application:
Cache user timelines and posts to optimize responsiveness, providing users with a seamless scrolling experience.
Financial Applications:
Cache frequently accessed market data to optimize portfolio management and real-time analytics.
Real use case:
As we had discussed above about dashboard management, let’s create a simplified version of it which is a common use case for many applications. We will be net sales for the given day. We have created a new segment from the dashboard named sales.
The code for it is given below.
const express = require("express");
const app = express();
const catalyst = require("zcatalyst-sdk-node");
// Mock function to simulate fetching total sales for a specific day from the database
async function fetchTotalSalesFromDatabase(day) {
console.log(`Fetching total sales for ${day} from the database...`);
// Simulated delay to mimic database query time
await new Promise((resolve) => setTimeout(resolve, 1000));
return Math.floor(Math.random() * 1000);
}
// Mock function to simulate fetching returns for a specific day from the database
async function fetchReturnsFromDatabase(day) {
console.log(`Fetching returns for ${day} from the database...`);
// Simulated database query
return Math.floor(Math.random() * 100);
}
// Function to calculate total daily sales minus returns, with caching
async function calculateNetSalesForDay(segment, day) {
// Attempt to fetch net sales from the cache
const cachedNetSales = await segment.get(day);
if (cachedNetSales.cache_value) {
console.log(`Fetching net sales for ${day} from the cache...`);
return cachedNetSales;
}
// If not found in cache, calculate net sales by fetching total sales and returns
const totalSales = await fetchTotalSalesFromDatabase(day);
const returns = await fetchReturnsFromDatabase(day);
const netSales = totalSales - returns;
// Update the cache with the calculated net sales
await segment.put(day, netSales, 2);
console.log(`Calculated net sales for ${day}: ${netSales}`);
return { day, netSales };
}
app.get("/net-sales/:day", async (req, res) => {
const catalystApp = catalyst.initialize(req, {
type: catalyst.type.advancedio
});
const day = req.params.day;
// Add your segment ID.
const segment = await catalystApp.cache().segment("2603000000017001");
// Calculate net sales for the specified day, considering caching
const netSales = await calculateNetSalesForDay(segment, day);
res.json(netSales);
});
const port = 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
module.exports = app;
For the sake of simplicity, we are mocking the calculations but in a real-world scenario, it can be a huge database call, or it might perform some complex manipulation on Excel files to get the number of sales.
Let’s say we have tons of users coming to check the sales, we definitely cannot afford to calculate sales on each request as it can crash the server. In such a case, we calculate it once for the first request and then serve the data in subsequent requests. The results can be seen below.
Since the calculated response is cached, no matter what the load, it will be returned fast!
Conclusion: Zoho Catalyst Cache – The Key to Accelerated Node.js Application Performance
In conclusion, Zoho Catalyst Cache proves to be a pivotal asset for developers seeking optimized application performance. By understanding its capabilities and integrating it seamlessly into Node.js applications, developers can unlock a new level of efficiency. Real-world use cases and performance optimization techniques underscore Zoho Catalyst Cache as a valuable tool, paving the way for faster response times, reduced load, and an elevated user experience. Embrace Zoho Catalyst Cache and propel your Node.js applications to new heights of performance.