nodejsnotes

Topic 003: NodeJS caching strategies

Topic 003: NodeJS caching strategies

caching strategies used to optimize performance and reduce latency in the applications.

1. In-Memory Caching

Tool Used: Node.js Memory (e.g., global variables)

In-memory caching stores data in the memory (RAM) of the application process. This method is extremely fast because accessing RAM is quicker than any form of persistent storage.

Example:

const cache = {};

function setCache(key, value) {
  cache[key] = {
    value,
    timestamp: Date.now(),
  };
}

function getCache(key) {
  const data = cache[key];
  if (data) {
    // Check if data is still valid (based on your own criteria)
    return data.value;
  }
  return null;
}

// Usage
setCache("user_123", { name: "John Doe", age: 30 });
const userData = getCache("user_123");

Use Case:

2. Distributed Caching

Tool Used: Redis

Redis is a popular in-memory data structure store used as a database, cache, and message broker. It supports various data structures such as strings, hashes, lists, sets, and more.

Example:

const redis = require("redis");
const client = redis.createClient();

client.on("error", (err) => {
  console.error("Redis error:", err);
});

function setCache(key, value, expiration = 3600) {
  client.setex(key, expiration, JSON.stringify(value));
}

function getCache(key, callback) {
  client.get(key, (err, data) => {
    if (err) {
      console.error("Redis get error:", err);
      callback(null);
    } else {
      callback(JSON.parse(data));
    }
  });
}

// Usage
setCache("user_123", { name: "John Doe", age: 30 });
getCache("user_123", (data) => {
  console.log(data);
});

Use Case:

3. HTTP Response Caching

Tool Used: Cache-Control Headers

HTTP response caching involves using caching headers to control how and when responses are cached by browsers or intermediary caches like CDNs.

Example:

const express = require("express");
const app = express();

app.get("/static-resource", (req, res) => {
  res.set("Cache-Control", "public, max-age=3600"); // Cache for 1 hour
  res.sendFile("/path/to/static/resource");
});

// Usage
app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

Use Case:

4. Database Query Caching

Tool Used: Redis for caching query results

Caching database queries can significantly reduce the load on the database and improve response times for frequently requested data.

Example:

const redis = require("redis");
const client = redis.createClient();
const db = require("./database"); // Assume a database module is available

function getUserFromDb(userId, callback) {
  db.query("SELECT * FROM users WHERE id = ?", [userId], (err, results) => {
    if (err) {
      return callback(err);
    }
    callback(null, results[0]);
  });
}

function getUser(userId, callback) {
  const cacheKey = `user_${userId}`;
  getCache(cacheKey, (data) => {
    if (data) {
      return callback(null, data);
    }
    getUserFromDb(userId, (err, user) => {
      if (err) {
        return callback(err);
      }
      setCache(cacheKey, user, 3600); // Cache for 1 hour
      callback(null, user);
    });
  });
}

// Usage
getUser(123, (err, user) => {
  if (err) {
    console.error(err);
  } else {
    console.log(user);
  }
});

Use Case:

5. Application-Level Caching

Tool Used: Node-Cache

Node-Cache is a simple in-memory caching module for Node.js.

Example:

const NodeCache = require("node-cache");
const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });

function setCache(key, value) {
  myCache.set(key, value);
}

function getCache(key) {
  return myCache.get(key);
}

// Usage
setCache("user_123", { name: "John Doe", age: 30 });
const userData = getCache("user_123");
console.log(userData);

Use Case:

Conclusion

Implementing caching effectively requires understanding the nature of the data and the specific use case. In-memory caching is fast but limited by the memory available on the server. Distributed caching with Redis provides scalability and reliability in a distributed system. HTTP caching helps reduce load on the server by leveraging client-side caching. Database query caching can offload expensive query operations and improve application performance. Each type of caching serves a specific purpose and, when combined, can lead to a highly efficient and responsive application.