# Caching Patterns

Redis caching strategies, cache invalidation, write-through/write-behind, TTL...

- Repository: https://github.com/vibeeval/vibecosystem (541 stars)
- Category: Writing
- License: MIT
- Last updated: 2026-08-08
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add vibeeval/vibecosystem --skill caching-patterns -g -a claude-code -y`
Codex: `npx skills add vibeeval/vibecosystem --skill caching-patterns -g -a codex -y`
Cursor: `npx skills add vibeeval/vibecosystem --skill caching-patterns -g -a cursor -y`
Gemini CLI: `npx skills add vibeeval/vibecosystem --skill caching-patterns -g -a gemini-cli -y`

## Description

Redis caching strategies, cache invalidation, write-through/write-behind, TTL management, and cache stampede protection.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Caching Patterns

Redis-based caching strategies for reducing latency and database load.

## Cache Key Design

```typescript
// Namespace:entity:id format
const CacheKeys = {
  market: (id: string) => `market:v1:${id}`,
  marketList: (filters: string) => `market:list:${filters}`,
  user: (id: string) => `user:v1:${id}`,
  userMarkets: (userId: string, page: number) => `user:${userId}:markets:${page}`,
  leaderboard: () => 'leaderboard:v1:global'
}

// Version prefix allows instant cache bust on schema change:
// bump v1 → v2 to invalidate all market keys without scanning
```

## Cache-Aside (Lazy Loading)

```typescript
import Redis from 'ioredis'

const redis = new Redis(process.env.REDIS_URL!)
const DEFAULT_TTL = 300  // 5 minutes

async function getOrSet<T>(
  key: string,
  loader: () => Promise<T>,
  ttl = DEFAULT_TTL
): Promise<T> {
  const cached = await redis.get(key)
  if (cached) return JSON.parse(cached) as T

  const value = await loader()
  await redis.setex(key, ttl, JSON.stringify(value))
  return value
}

// Usage
async function getMarket(id: string): Promise<Market> {
  return getOrSet(
    CacheKeys.market(id),
    () => db.market.findUniqueOrThrow({ where: { id } }),
    300
  )
}
```

## Write-Through Pattern

```typescript
// Write to cache AND database together - cache is always fresh
async function updateMarket(id: string, data: UpdateMarketDto): Promise<Market> {
  const updated = await db.market.update({ where: { id }, data })

  // Synchronously update cache so next read is fresh
  await redis.setex(CacheKeys.market(id), DEFAULT_TTL, JSON.stringify(updated))

  return updated
}

async function deleteMarket(id: string): Promise<void> {
  await db.market.delete({ where: { id } })
  await redis.del(CacheKeys.market(id))
}
```

## Write-Behind (Write-Back) Pattern

```typescript
// Write to cache immediately, flush to DB asynchronously (higher throughput)
// Risk: data loss on crash if queue not durable

The rest: https://github.com/vibeeval/vibecosystem/blob/HEAD/skills/caching-patterns/SKILL.md
