TTLs and key design

Every cached value should have a TTL. Redis will delete the key automatically after the window expires. The TTL is your safety net: even if invalidation logic breaks somewhere, stale data corrects itself within the window. Use it.

Picking a TTL is a tradeoff. A 10 second TTL keeps data fresh but barely helps the database. A one hour TTL reduces database load dramatically but serves stale data for up to an hour. A 60 second TTL is a reasonable default for most APIs. Make the call based on how fresh the data needs to be, not the other way around.

after/services/book.service.ts
typescript
// A single list key for all books
const BOOKS_ALL_KEY = 'books:all';

// A per-book key built from the id
function bookKey(id: number) {
  return 'books:' + id;
}

// Usage
await cacheSet('books:all', books);
await cacheSet(bookKey(42), oneBook);

// Later, invalidate everything under books:* in one shot
await cacheDelete('books:*');

Key naming that makes invalidation easy.

Use a prefix that names the resource (books) followed by a colon and the specific identifier. books:all for the full list, books:42 for one book. When you need to invalidate everything related to books, you delete books:*. One glob, all related keys gone. Good naming is what makes invalidation simple.

One production caveat on the keys pattern. The Redis KEYS command scans the entire keyspace and blocks Redis while it runs. Fine for development and small datasets. In production with millions of keys, switch to SCAN or maintain a small set of known cache keys you can iterate. The pattern matters, the exact command behind it changes with scale.

Quiz: Quiz

Loading practice…