How to make node.js API 10 x fast using caching

Ahmed salman
4 min readJan 18, 2024

--

Improving the performance of your Node.js API by implementing caching is a powerful strategy. Caching involves storing and retrieving frequently used data, reducing the need to repeatedly fetch or compute the same information. This can lead to significant speed improvements by minimizing resource-intensive operations. Here’s an introduction on how to make your Node.js API 10 times faster using caching:

1. Understanding Caching:

  • What is Caching? Caching is the process of storing data in a temporary storage area to accelerate access to frequently requested information.
  • Why Use Caching? Caching reduces the need to recompute or fetch data from slower sources (e.g., databases, external APIs), leading to faster response times and improved overall system performance.

2. Types of Caching in Node.js:

  • In-Memory Caching: Utilizes the server’s memory to store frequently accessed data. Libraries like memory-cache facilitate easy implementation.
  • Middleware-based Caching: Integrates caching directly into route handlers using middleware, such as express-cache-headers.
  • External Caching Systems: Leveraging external systems like Redis or Memcached for distributed caching across multiple servers.

3. Implementing In-Memory Caching:

  • Use libraries like memory-cache to store and retrieve data in the server's memory.
  • Set a time-to-live (TTL) for cached data to control how long the data remains valid.

Example using memory-cache:

Install the package using npm:

npm install memory-cache
  • Then, implement in-memory caching in your Node.js application:
const express = require('express');
const cache = require('memory-cache');

const app = express();

app.get('/api/data', (req, res) => {
const cachedData = cache.get('cachedData');
if (cachedData) {
// Return cached data
return res.json(cachedData);
}

// Fetch data from the database or external API
const newData = fetchData();

// Cache the data for future use
cache.put('cachedData', newData, 10 * 60 * 1000); // Cache for 10 minutes

res.json(newData);
});

const fetchData = () => {
// Implement your logic to fetch data
};

const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

Resources:

  • memory-cache npm package
  • In-Memory Data Store in Node.js

4. Use a Caching Middleware:

Caching middleware allows you to integrate caching directly into your route handlers. The express-cache-headers middleware simplifies this process.

Example using express-cache-headers middleware:

Install the package using npm:

npm install express-cache-headers

Then, use it in your Node.js application:

const express = require('express');
const cacheHeaders = require('express-cache-headers');
const app = express();

app.get('/api/data', cacheHeaders({ ttl: 600 }), (req, res) => {
// Fetch data from the database or external API
const newData = fetchData();

res.json(newData);
});

const fetchData = () => {
// Implement your logic to fetch data
};

const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

Resources:

  • express-cache-headers npm package
  • HTTP Caching in Express.js

5. Redis or Memcached:

For distributed caching or when running your API on multiple servers, external caching systems like Redis or Memcached are effective choices.

1. What is Redis?

  • Redis (Remote Dictionary Server) is an in-memory data structure store used as a database, cache, and message broker.
  • It supports various data structures like strings, hashes, lists, sets, and more.

2. Key Features of Redis:

  • In-Memory Storage: Data is stored in RAM, providing fast read and write operations.
  • Persistence: Supports optional persistence to disk for durability.
  • Data Structures: Offers a variety of data structures, allowing flexibility in storing and manipulating data.
  • Atomic Operations: Redis commands are atomic, ensuring consistency in multi-operation transactions.
  • Pub/Sub Messaging: Implements publish/subscribe for real-time message broadcasting.

Example using Redis:

Install the redis package using npm:

npm install redis

Implement Redis caching in your Node.js application:

const express = require('express');
const redis = require('redis');
const client = redis.createClient();

const app = express();

app.get('/api/data', async (req, res) => {
const cachedData = await getAsync('cachedData');
if (cachedData) {
// Return cached data
return res.json(JSON.parse(cachedData));
}

// Fetch data from the database or external API
const newData = fetchData();

// Cache the data in Redis for future use
client.set('cachedData', JSON.stringify(newData), 'EX', 600); // Cache for 10 minutes

res.json(newData);
});

const getAsync = (key) => {
return new Promise((resolve, reject) => {
client.get(key, (err, reply) => {
if (err) {
reject(err);
} else {
resolve(reply);
}
});
});
};

const fetchData = () => {
// Implement your logic to fetch data
};

const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

Resources:

  • redis npm package
  • Redis — Introduction to Caching

6. Considerations and Best Practices:

  • Cache Invalidation: Ensure proper cache invalidation strategies to keep data up-to-date.
  • Monitor and Tune: Regularly monitor cache performance and adjust caching strategies based on usage patterns and data volatility.

By incorporating caching techniques into your Node.js API, you can significantly enhance its speed and responsiveness, providing a better experience for users. Experiment with different caching strategies based on your specific use case and system requirements.

finally if you enjoy reading Follow me and wait for the next topic
i will happy if we connect in LinkedIn for any discussion

--

--