Caching Strategies

SkillDatabases & data

Application caching patterns. Redis caching, in-memory caches, HTTP caching, cache invalidation strategies, cache-aside, write-through, and CDN caching.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Caching Strategies skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/best-practices/caching-strategies/SKILL.md and read by ahel’s review.

Cache-Aside (Lazy Loading) — Most Common

async function getUser(id: string): Promise<User> {
  const cached = await redis.get(`user:${id}`);
  if (cached) return JSON.parse(cached);

  const user = await db.user.findUnique({ where: { id } });
  if (user) {
    await redis.set(`user:${id}`, JSON.stringify(user), 'EX', 3600); // 1h TTL
  }
  return user;
}

// Invalidate on update
async function updateUser(id: string, data: UpdateUserDto): Promise<User> {
  const user = await db.user.update({ where: { id }, data });
  await redis.del(`user:${id}`);
  return user;
}

Write-Through

async function updateProduct(id: string, data: UpdateDto): Promise<Product> {
  const product = await db.product.update({ where: { id }, data });
  await redis.set(`product:${id}`, JSON.stringify(product), 'EX', 3600);
  return product;
}

HTTP Caching

// Express middleware
app.get('/api/products', (req, res) => {
  res.set({
    'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',
    'ETag': generateETag(products),
  });
  res.json(products);
});

// Conditional requests
app.get('/api/products/:id', (req, res) => {
  const product = getProduct(req.params.id);
  const etag = generateETag(product);

  if (req.headers['if-none-match'] === etag) {
    return res.status(304).end();
  }

  res.set({ ETag: etag, 'Cache-Control': 'private, max-age=0, must-revalidate' });
  res.json(product);
});

Cache-Control Cheat Sheet

DirectiveUse Case
public, max-age=3600Static assets, CDN-cacheable
private, max-age=60User-specific data
no-cacheAlways revalidate (ETag/Last-Modified)
no-storeSensitive data (banking, health)
stale-while-revalidate=300Serve stale, refresh in background

Redis Caching Patterns

// Hash for structured data
await redis.hset(`user:${id}`, { name, email, plan });
const user = await redis.hgetall(`user:${id}`);

// Sorted set for leaderboards
await redis.zadd('leaderboard', score, `user:${id}`);
const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');

// Cache with refresh-ahead
async function getWithRefresh<T>(key: string, ttl: number, fetcher: () => Promise<T>): Promise<T> {
  const cached = await redis.get(key);
  if (cached) {
    const { data, expiresAt } = JSON.parse(cached);
    // Refresh in background if nearing expiry
    if (Date.now() > expiresAt - ttl * 200) {
      fetcher().then((fresh) =>
        redis.set(key, JSON.stringify({ data: fresh, expiresAt: Date.now() + ttl * 1000 }), 'EX', ttl)
      );
    }
    return data;
  }
  const data = await fetcher();
  await redis.set(key, JSON.stringify({ data, expiresAt: Date.now() + ttl * 1000 }), 'EX', ttl);
  return data;
}

Invalidation Strategies

StrategyDescription
TTL-basedSet expiration, tolerate staleness
Event-drivenInvalidate on write events
Tag-basedGroup keys by tag, purge by tag
Versioned keysuser:v2:${id} — change version to invalidate all

Anti-Patterns

Anti-PatternFix
No TTL on cache entriesAlways set TTL to prevent stale data
Cache stampede (many misses at once)Use locking or stale-while-revalidate
Caching mutable data without invalidationInvalidate on writes or use short TTL
Caching everythingCache hot data only; measure hit rates
Serializing large objectsCache only needed fields

Production Checklist

  • TTL set on all cache entries
  • Cache invalidation on data mutations
  • Hit rate monitoring (aim for >90%)
  • Memory limits configured on Redis
  • Cache key naming convention documented
  • Graceful fallback when cache unavailable

Signals

GitHub stars
33
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
caching-strategies
Source
github.com/claude-dev-suite/claude-dev-suite