Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
The Server Half  ›  Lesson

Where a Redis Cache Fits

Redis 14 minIn the cache-aside pattern the server checks Redis first, falls back to the database on a miss and stores the result with an expiry, and deletes the key when a write makes it wrong.

Where a Redis Cache Fits

Sprout grows, and its public "Most popular plants" page is opened thousands of times an hour. Every visit runs the same query, which counts plants across every user in the database. Redis, a very fast in-memory key-value store, can keep the answer ready so that most visits never reach PostgreSQL. The catch: a cache is a copy, and copies go stale.

The rule

Check the cache, fall back to the database, forget on change.

This pattern is called cache-aside, because the cache sits beside the database and your code decides when to use each:

app.get('/api/popular', async (req, res) => {
  const cached = await redis.get('popular');
  if (cached) return res.json(JSON.parse(cached));        // hit

  const { rows } = await pool.query(                      // miss
    'SELECT name, COUNT(DISTINCT owner_id) AS owners FROM plants GROUP BY name ORDER BY owners DESC LIMIT 10'
  );
  await redis.set('popular', JSON.stringify(rows), { EX: 600 });
  res.json(rows);
});
  • Hit. The key exists, so the answer comes straight from memory in about a millisecond, and the database is not touched.
  • Miss. Run the real query, store the result as text under a key with an expiry (EX: 600 means 600 seconds), then answer.
  • Expiry puts a ceiling on staleness: this answer is never more than ten minutes old.
  • Forgetting. When a write makes a cached answer wrong and waiting for expiry is not acceptable, the write handler deletes the key with await redis.del('popular'), so the next read rebuilds it.

In the round trip, Redis sits between the server and the database. The browser never talks to Redis, just as it never talks to PostgreSQL. Full-stack apps also use Redis for other short-lived, fast-changing data, such as rate-limit counters, session records and background job queues.

Not everything should be cached. A good candidate is read far more often than it changes, costly to compute, and fine if slightly old. A user's own plant list is a poor fit: right after watering a plant, they expect to see it at once. Measure first, and cache the endpoints that are actually slow.

The shortcut

For any endpoint you want to cache, answer two questions. "How stale may this be?" gives the expiry. "Which writes change it?" gives the places that must delete the key. If you cannot answer the second, keep the expiry short.

Three visits to the popular pageStep 1 of 4
  1. 09:00, first visit

    Miss. The query runs, the result is stored for 600 seconds, and the visitor gets the answer.

Drills

Answer fast — trust the rule.

quick drill

In cache-aside, what happens on a cache miss?

quick drill

What does { EX: 600 } do when the key is set?

quick drill

Which Sprout data is the worst candidate for caching?

quick drill

An admin fixes a typo in a cached care guide and it must show at once. What should the edit handler do besides updating PostgreSQL?

Remember

  • Check the cache, fall back to the database, forget on change.
  • Shortcut: "How stale may this be?" sets the expiry; "Which writes change it?" lists where to delete the key.
  • Trap: caching everything. Cache what is read often, slow to compute and fine slightly old.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainCaching the thirsty badge

Every page in Sprout shows a badge, 'N plants thirsty today', and computing it on each page load is slowing the database. Explain whether you would cache it, what key and expiry you would choose, and which writes would need to delete the key.