Course contentsShow
← Node.js
Lesson 1331 of 1,98012. Caching Strategies and Application SpeedFree lesson

Negative Caching Strategies

You will cache the absence of data to prevent expensive database lookups for non-existent keys.

In this lesson, you will learn how to implement "Negative Caching" to stop your application from wasting resources on repetitive database lookups for data that simply does not exist.

The Problem: The "Cache Penetration" Tax

Imagine your application receives a request for a user ID that doesn't exist in your database. Your code checks the cache (a miss), queries the database (an expensive IO operation), receives nothing back, and returns a 404. If a malicious actor or a bug causes thousands of requests for non-existent IDs, your database will be hammered with these "ghost" lookups. This phenomenon is known as cache penetration.

Implementing Negative Caching

Negative caching solves this by treating the absence of data as a cacheable result. When you perform a database query and find nothing, instead of simply returning the 404, you store a special "sentinel" value—such as null or a specific string like "NOT_FOUND"—in your cache with a short TTL (Time-To-Live).

Here is a simple pattern using a generic cache:

async function getUser(userId) {
  const cachedValue = await cache.get(`user:${userId}`);

  // If the key exists, it means we already know this user is missing
  if (cachedValue === "NOT_FOUND") return null;
  if (cachedValue) return JSON.parse(cachedValue);

  const user = await db.users.findById(userId);

  if (!user) {
    // Cache the absence for a short period to block future lookups
    await cache.set(`user:${userId}`, "NOT_FOUND", { ttl: 60 });
    return null;
  }

  await cache.set(`user:${userId}`, JSON.stringify(user));
  return user;
}

Why it Matters

By caching the null result, the next request for that same invalid ID will be handled by the cache in microseconds, completely bypassing your database. The short TTL is vital here; if the user record is eventually created in the database, the cache entry will expire, ensuring the system remains consistent without requiring complex manual invalidation for data that wasn't there to begin with.

Key Takeaway: Negative caching prevents "cache penetration" by storing a sentinel value for non-existent records, effectively shielding your database from redundant IO operations for missing data.