advanced-caching-strategies

Multi-layer caching strategies across CDN, browser, server, and database. PROACTIVELY activate for: (1) HTTP caching headers, (2) CDN configuration, (3) Server-side caching with Redis, (4) Cache invalidation strategies, (5) ETag implementation. Triggers: "caching", "cache strategy", "CDN", "browser cache", "server cache", "redis", "cache invalidation", "ETag", "Cache-Control"

181 stars

Best use case

advanced-caching-strategies is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Multi-layer caching strategies across CDN, browser, server, and database. PROACTIVELY activate for: (1) HTTP caching headers, (2) CDN configuration, (3) Server-side caching with Redis, (4) Cache invalidation strategies, (5) ETag implementation. Triggers: "caching", "cache strategy", "CDN", "browser cache", "server cache", "redis", "cache invalidation", "ETag", "Cache-Control"

Teams using advanced-caching-strategies should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/advanced-caching-strategies/SKILL.md --create-dirs "https://raw.githubusercontent.com/majiayu000/claude-skill-registry/main/skills/data/advanced-caching-strategies/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/advanced-caching-strategies/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How advanced-caching-strategies Compares

Feature / Agentadvanced-caching-strategiesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Multi-layer caching strategies across CDN, browser, server, and database. PROACTIVELY activate for: (1) HTTP caching headers, (2) CDN configuration, (3) Server-side caching with Redis, (4) Cache invalidation strategies, (5) ETag implementation. Triggers: "caching", "cache strategy", "CDN", "browser cache", "server cache", "redis", "cache invalidation", "ETag", "Cache-Control"

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Advanced Caching Strategies

This skill provides guidance on designing and implementing multi-layered caching strategies across the full application stack (CDN, browser, server, database) to minimize latency, reduce server load, and improve overall application resilience and user experience.

## The Cache Hierarchy

Caching can be implemented at multiple layers, from closest to the user to closest to the data source:

1. **Browser Cache**: Client-side caching (HTTP caching, LocalStorage, IndexedDB)
2. **CDN Edge Cache**: Geographically distributed caching (Vercel Edge, CloudFront, Cloudflare)
3. **Server-Side Cache**: Application-level caching (Redis, in-memory)
4. **Database Cache**: Query result caching, connection pooling

**Goal**: Serve content from the closest, fastest cache layer possible.

## Browser Caching

Browser caching reduces network requests by storing resources locally.

### HTTP Cache-Control Headers

The `Cache-Control` header controls how and for how long browsers cache responses.

#### Immutable Static Assets

```http
# For assets with content-addressed filenames (e.g., app.abc123.js)
Cache-Control: public, max-age=31536000, immutable
```

- **public**: Can be cached by browsers and CDNs
- **max-age=31536000**: Cache for 1 year (in seconds)
- **immutable**: Never revalidate (file name changes when content changes)

**Next.js**: Automatically sets this for `/_next/static/` files

#### Dynamic HTML Pages

```http
# For HTML pages that change periodically
Cache-Control: public, max-age=0, must-revalidate
```

- **max-age=0**: Revalidate on every request
- **must-revalidate**: Must check server before using stale cache

Or with stale-while-revalidate:
```http
Cache-Control: public, max-age=60, stale-while-revalidate=86400
```

- Serve from cache for 60s
- If 60s-24h old, serve stale content while revalidating in background

#### API Responses

```http
# User-specific data (don't cache)
Cache-Control: private, no-store

# Public data that changes occasionally
Cache-Control: public, max-age=300, stale-while-revalidate=600
```

- **private**: Only browser cache (not CDN)
- **no-store**: Don't cache at all
- **stale-while-revalidate**: Serve stale data while fetching fresh data

### ETag and Conditional Requests

ETags enable efficient revalidation without re-downloading unchanged content.

#### Server Implementation (Next.js API Route)

```ts
// app/api/data/route.ts
import { NextResponse } from 'next/server'
import crypto from 'crypto'

export async function GET(request: Request) {
  const data = await fetchData()
  const content = JSON.stringify(data)

  // Generate ETag from content hash
  const etag = crypto.createHash('md5').update(content).digest('hex')

  // Check If-None-Match header
  const clientEtag = request.headers.get('if-none-match')

  if (clientEtag === etag) {
    // Content hasn't changed
    return new NextResponse(null, { status: 304 })
  }

  // Content changed, send full response
  return NextResponse.json(data, {
    headers: {
      'ETag': etag,
      'Cache-Control': 'public, max-age=300',
    },
  })
}
```

#### Python FastAPI Implementation

```python
from fastapi import FastAPI, Request, Response
import hashlib
import json

app = FastAPI()

@app.get("/api/data")
async def get_data(request: Request):
    data = await fetch_data()
    content = json.dumps(data)

    # Generate ETag
    etag = hashlib.md5(content.encode()).hexdigest()

    # Check If-None-Match
    if request.headers.get("if-none-match") == etag:
        return Response(status_code=304)

    # Return with ETag
    return Response(
        content=content,
        headers={
            "ETag": etag,
            "Cache-Control": "public, max-age=300"
        }
    )
```

### LocalStorage and IndexedDB

For application state and data that doesn't need to be in HTTP cache.

```ts
// Simple cache wrapper for localStorage
class BrowserCache {
  static set(key: string, value: any, ttlMs: number) {
    const item = {
      value,
      expiry: Date.now() + ttlMs,
    }
    localStorage.setItem(key, JSON.stringify(item))
  }

  static get(key: string) {
    const itemStr = localStorage.getItem(key)
    if (!itemStr) return null

    const item = JSON.parse(itemStr)
    if (Date.now() > item.expiry) {
      localStorage.removeItem(key)
      return null
    }

    return item.value
  }
}

// Usage
BrowserCache.set('user-prefs', preferences, 7 * 24 * 60 * 60 * 1000) // 7 days
const prefs = BrowserCache.get('user-prefs')
```

## CDN Caching

CDNs cache content at edge locations close to users, reducing latency and server load.

### Vercel Edge Network (Next.js)

Vercel automatically caches static assets and certain dynamic routes.

```ts
// app/products/page.tsx
export const revalidate = 3600 // Cache for 1 hour

export default async function ProductsPage() {
  const products = await fetch('https://api.example.com/products', {
    next: { revalidate: 3600 }
  }).then(r => r.json())

  return <ProductGrid products={products} />
}
```

### Custom CDN Headers

```ts
// app/api/public-data/route.ts
export async function GET() {
  const data = await fetchPublicData()

  return NextResponse.json(data, {
    headers: {
      'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
      'CDN-Cache-Control': 'max-age=7200',
    },
  })
}
```

- **s-maxage**: CDN cache duration (overrides max-age for shared caches)
- **CDN-Cache-Control**: Cloudflare-specific directive

### Cache Key Configuration

Ensure cache keys include relevant parameters:

```ts
// BAD: Same cache for all users
fetch(`https://api.example.com/dashboard`)

// GOOD: User-specific cache key
fetch(`https://api.example.com/dashboard`, {
  headers: {
    'x-user-id': userId,
  },
  cache: 'no-store', // Don't cache user-specific data in CDN
})
```

### CDN Purging

```ts
// app/api/revalidate/route.ts
import { revalidatePath, revalidateTag } from 'next/cache'

export async function POST(request: Request) {
  const { path, tag } = await request.json()

  if (path) {
    revalidatePath(path) // Purge specific path
  }

  if (tag) {
    revalidateTag(tag) // Purge all fetches with this tag
  }

  return Response.json({ revalidated: true })
}
```

## Server-Side Caching

Application-level caching reduces database load and improves response times.

### Next.js React cache()

```ts
// lib/data.ts
import { cache } from 'react'

export const getUser = cache(async (id: string) => {
  // This function is memoized during a single request
  const user = await db.query('SELECT * FROM users WHERE id = ?', [id])
  return user
})

// Can be called multiple times in components without re-fetching
const user1 = await getUser('123')
const user2 = await getUser('123') // Returns memoized result
```

### Next.js unstable_cache

```ts
import { unstable_cache } from 'next/cache'

export const getCachedProducts = unstable_cache(
  async () => {
    return await db.query('SELECT * FROM products')
  },
  ['products-list'], // Cache key
  {
    revalidate: 3600, // Cache for 1 hour
    tags: ['products'], // For on-demand revalidation
  }
)
```

### Redis Caching (Python)

```python
import redis
import json
from functools import wraps

redis_client = redis.Redis(host='localhost', port=6379, db=0)

def cache_result(ttl: int = 300):
    """Decorator for caching function results in Redis"""
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            # Generate cache key from function name and arguments
            cache_key = f"{func.__name__}:{args}:{kwargs}"

            # Try to get from cache
            cached = redis_client.get(cache_key)
            if cached:
                return json.loads(cached)

            # Cache miss - execute function
            result = await func(*args, **kwargs)

            # Store in cache
            redis_client.setex(
                cache_key,
                ttl,
                json.dumps(result)
            )

            return result

        return wrapper
    return decorator

# Usage
@cache_result(ttl=600)
async def get_user_profile(user_id: str):
    return await db.fetch_one(
        "SELECT * FROM users WHERE id = ?",
        user_id
    )
```

### LRU Cache (Python)

For single-process applications:

```python
from functools import lru_cache

@lru_cache(maxsize=1000)
def get_exchange_rate(from_currency: str, to_currency: str) -> float:
    """Cache recent exchange rate lookups"""
    response = requests.get(
        f"https://api.example.com/rate/{from_currency}/{to_currency}"
    )
    return response.json()['rate']

# Clear cache when needed
get_exchange_rate.cache_clear()
```

## Database Caching

Optimize database performance through caching and connection pooling.

### Query Result Caching

```python
# Using Redis for query result caching
async def get_popular_products():
    cache_key = "popular_products"

    # Check cache
    cached = await redis_client.get(cache_key)
    if cached:
        return json.loads(cached)

    # Cache miss - query database
    products = await db.fetch_all(
        """
        SELECT * FROM products
        WHERE views > 1000
        ORDER BY views DESC
        LIMIT 20
        """
    )

    # Cache for 10 minutes
    await redis_client.setex(
        cache_key,
        600,
        json.dumps(products)
    )

    return products
```

### Connection Pooling

```python
# PostgreSQL connection pool
import asyncpg

pool = await asyncpg.create_pool(
    host='localhost',
    database='mydb',
    user='user',
    password='password',
    min_size=10,    # Minimum connections
    max_size=20,    # Maximum connections
)

# Use pooled connection
async with pool.acquire() as connection:
    result = await connection.fetch('SELECT * FROM users')
```

### Prepared Statements

```python
# Reuse parsed queries
async with pool.acquire() as conn:
    stmt = await conn.prepare('SELECT * FROM users WHERE id = $1')

    # Execute multiple times without re-parsing
    user1 = await stmt.fetchrow(123)
    user2 = await stmt.fetchrow(456)
```

## Cache Invalidation Strategies

"There are only two hard things in Computer Science: cache invalidation and naming things."

### Time-Based (TTL)

Simplest strategy: data expires after a set time.

```ts
// Cache for 5 minutes
fetch('https://api.example.com/data', {
  next: { revalidate: 300 }
})
```

**Pros**: Simple, predictable
**Cons**: Data can be stale for up to TTL duration

### On-Demand Invalidation

Invalidate cache when data changes.

```ts
// When product is updated
await fetch('/api/revalidate', {
  method: 'POST',
  body: JSON.stringify({ tag: 'products' }),
})
```

**Pros**: Always fresh data
**Cons**: Requires webhook/trigger on every update

### Stale-While-Revalidate

Serve stale content while fetching fresh data in the background.

```http
Cache-Control: max-age=60, stale-while-revalidate=86400
```

**Pros**: Fast response (always from cache), eventually consistent
**Cons**: Users may see stale data briefly

### Write-Through Cache

Update cache atomically with database write.

```python
async def update_user(user_id: str, data: dict):
    # Update database
    await db.execute(
        "UPDATE users SET name = $1 WHERE id = $2",
        data['name'],
        user_id
    )

    # Update cache
    cache_key = f"user:{user_id}"
    await redis_client.setex(
        cache_key,
        3600,
        json.dumps(data)
    )
```

**Pros**: Cache always consistent with database
**Cons**: Slower writes (two operations)

### Cache-Aside Pattern

Application checks cache, fetches from DB on miss, then populates cache.

```python
async def get_user(user_id: str):
    cache_key = f"user:{user_id}"

    # Check cache
    cached = await redis_client.get(cache_key)
    if cached:
        return json.loads(cached)

    # Cache miss - fetch from DB
    user = await db.fetch_one(
        "SELECT * FROM users WHERE id = $1",
        user_id
    )

    # Populate cache
    await redis_client.setex(cache_key, 3600, json.dumps(user))

    return user
```

**Pros**: Only caches accessed data
**Cons**: Cache can become stale if DB updated elsewhere

## Anti-Patterns

### Caching User-Specific Data in Public Cache

```http
# BAD: User data cached in CDN
Cache-Control: public, max-age=3600
```

**Result**: User A sees User B's data

**Fix**: Use `private` or `no-store` for user-specific data

### No Cache-Busting for Static Assets

```html
<!-- BAD: Users stuck with old version -->
<script src="/app.js"></script>

<!-- GOOD: Content-addressed filename -->
<script src="/app.abc123.js"></script>
```

**Next.js handles this automatically** for `/_next/static/` files.

### Long TTL Without Invalidation Strategy

```ts
// BAD: Data could be stale for a month
fetch(url, { next: { revalidate: 2592000 } })
```

**Fix**: Use shorter TTL or implement on-demand invalidation.

### Not Varying Cache by Request Headers

```ts
// BAD: Same cache for all languages
fetch('/api/content')

// GOOD: Cache varies by Accept-Language
fetch('/api/content', {
  headers: {
    'Accept-Language': locale,
  },
})
```

### Ignoring Cache Stampede

Multiple requests fetch same data simultaneously when cache expires (thundering herd).

**Fix**: Use request coalescing or stale-while-revalidate.

## Caching Strategy Decision Tree

```
Is the data user-specific?
├─ YES → Use private cache or no-store
│   └─ High traffic? → Server-side cache (Redis) with user-specific keys
└─ NO → Is the data static?
    ├─ YES → Cache-Control: public, max-age=31536000, immutable
    └─ NO → How often does it change?
        ├─ Frequently (< 1 min) → Cache-Control: max-age=60, stale-while-revalidate
        ├─ Periodically (< 1 hour) → Cache-Control: max-age=300 + on-demand invalidation
        └─ Rarely (> 1 hour) → Cache-Control: max-age=3600
```

## Caching Checklist

- [ ] Static assets cached with long TTL and immutable flag
- [ ] HTML pages use stale-while-revalidate pattern
- [ ] User-specific data NOT cached in CDN (use private/no-store)
- [ ] ETags implemented for efficient revalidation
- [ ] CDN configured for public cacheable routes
- [ ] Redis/in-memory cache for hot database queries
- [ ] Database connection pooling configured
- [ ] Cache invalidation strategy defined and implemented
- [ ] Cache keys include relevant parameters (avoid cache poisoning)
- [ ] Monitoring for cache hit rates and effectiveness

## Performance Impact

Effective caching can:
- **Reduce server load**: 70-90% reduction for cacheable content
- **Improve response time**: 10-100x faster (edge cache vs origin)
- **Reduce database load**: 80-95% reduction for popular queries
- **Improve reliability**: Serve stale content during outages

Related Skills

advanced-skill-creator

181
from majiayu000/claude-skill-registry

Meta-skill that generates domain-specific skills using advanced reasoning techniques. PROACTIVELY activate for: (1) Create/build/make skills, (2) Generate expert panels for any domain, (3) Design evaluation frameworks, (4) Create research workflows, (5) Structure complex multi-step processes, (6) Instantiate templates with parameters. Triggers: "create a skill for", "build evaluation for", "design workflow for", "generate expert panel for", "how should I approach [complex task]", "create skill", "new skill for", "skill template", "generate skill"

advanced-rendering

181
from majiayu000/claude-skill-registry

Master high-performance rendering for large datasets with Datashader. Use this skill when working with datasets exceeding 100M+ points, optimizing visualization performance, or implementing efficient rendering strategies with rasterization and colormapping techniques.

Advanced React Clean Integration

181
from majiayu000/claude-skill-registry

Integrate React with clean architecture without framework leakage using hooks as adapters and presenters. Use when connecting React to domain logic, designing hook-based DI, or isolating UI from business rules.

Advanced RE Analysis

181
from majiayu000/claude-skill-registry

Specialized reverse engineering analysis workflows for binary analysis, pattern recognition, and vulnerability assessment

advanced-patterns

181
from majiayu000/claude-skill-registry

Advanced T-SQL patterns and techniques for SQL Server. Use this skill when: (1) User needs help with CTEs or recursive queries, (2) User asks about APPLY operator, (3) User wants MERGE or OUTPUT clause help, (4) User works with temporal tables, (5) User needs In-Memory OLTP guidance, (6) User asks about advanced grouping (ROLLUP, CUBE, GROUPING SETS).

advanced-oscal-validator

181
from majiayu000/claude-skill-registry

Perform comprehensive OSCAL validation using community-inspired patterns including JSON schema validation, business rule validation, cross-reference checking, and best practices from IBM Trestle, oscal-pydantic, and Lula. Use for thorough document quality assurance.

Advanced Modular Library Design

181
from majiayu000/claude-skill-registry

Design modular libraries with clear package boundaries, feature-first organization, and clean API surfaces. Use when structuring monorepos, defining module boundaries, or designing library APIs.

advanced-memory-skill-creator

181
from majiayu000/claude-skill-registry

Use when planning, scaffolding, validating, or packaging Claude skills inside Advanced Memory MCP.

advanced-memoization-strategies

181
from majiayu000/claude-skill-registry

Apply principled memoization techniques to reduce re-rendering without introducing correctness bugs.

advanced-math-trading/robustness-risk

181
from majiayu000/claude-skill-registry

Tail risk, EVT, regularization, validation guardrails, and common pitfalls.

advanced-math-trading/portfolio-factors

181
from majiayu000/claude-skill-registry

Factor modeling and portfolio construction (Markowitz, Black-Litterman, constraints, turnover).

advanced-math-trading/foundations-core

181
from majiayu000/claude-skill-registry

Probability, moments/tails, Bayes, and statistical learning foundations for systematic trading.