Install
$ agentstack add skill-zebbern-claude-code-guide-caching ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
WHENTOUSE
- When implementing a cache layer (in-memory, Redis, CDN) for an API or service.
- When choosing TTL values or invalidation strategies for cached data.
- When designing cache key schemas to avoid collisions or stale-data bugs.
- When reviewing code that reads from or writes to any cache.
- When debugging stale data, cache stampedes, or inconsistent responses.
- When configuring TanStack Query
staleTime/gcTimefor client-side caching.
INVALIDATION
- [P0-MUST] Define an invalidation strategy for every cache. Stale data is worse than no cache.
- [P0-MUST] Invalidate caches when the underlying data changes — do not rely solely on TTL expiry.
- [P1-SHOULD] Prefer event-driven invalidation (on write/update/delete) over time-based expiry alone.
- [P1-SHOULD] Use cache versioning (include a version key) when data schemas change.
TTL_GUIDELINES
- [P1-SHOULD] Set TTLs based on data volatility: static config (hours/days), user profiles (minutes), real-time data (seconds or no cache).
- [P1-SHOULD] Use stale-while-revalidate: serve stale data immediately while refreshing in the background.
- [P2-MAY] Use shorter TTLs in development and longer TTLs in production.
CACHE_KEYS
- [P0-MUST] Include all query parameters that affect the result in the cache key.
- [P1-SHOULD] Use a consistent key format:
::(e.g.,user:123:profile,products:list:page=2). - [P1-SHOULD] Namespace keys by service or module to prevent collisions.
- [P2-MAY] Hash long or complex keys to keep storage efficient.
CACHE_LAYERS
- [P1-SHOULD] Use the appropriate cache layer for the use case:
| Layer | Best For | TTL Range | |-------|----------|-----------| | In-memory (Map, LRU) | Hot data, single-instance apps | Seconds to minutes | | Redis / Memcached | Shared cache across instances, sessions | Minutes to hours | | CDN / Edge | Static assets, public API responses | Hours to days | | HTTP cache headers | Browser caching, API responses | Varies by resource |
- [P1-SHOULD] Layer caches: check memory → Redis → origin. Write-through on miss.
WHENNOTTO_CACHE
- [P0-MUST] Do not cache user-specific sensitive data (auth tokens, payment info) in shared caches.
- [P1-SHOULD] Do not cache rapidly changing data where staleness causes incorrect behavior (inventory counts, real-time pricing).
- [P1-SHOULD] Do not cache error responses — use short TTL or skip caching on failure.
- [P2-MAY] Avoid caching when the computation is cheap and the data set is small.
CODE_EXAMPLES
In-memory LRU cache with TTL
const cache = new Map();
const MAX_SIZE = 500;
export function getOrSet(key: string, ttlMs: number, compute: () => T): T {
const entry = cache.get(key);
if (entry && entry.expires > Date.now()) return entry.value as T;
const value = compute();
if (cache.size >= MAX_SIZE) {
// Evict oldest entry (first inserted)
const oldest = cache.keys().next().value!;
cache.delete(oldest);
}
cache.set(key, { value, expires: Date.now() + ttlMs });
return value;
}
Redis stale-while-revalidate with ioredis
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
export async function swr(
key: string,
freshSec: number,
staleSec: number,
fetcher: () => Promise,
): Promise {
const raw = await redis.get(key);
if (raw) {
const { value, createdAt } = JSON.parse(raw) as { value: T; createdAt: number };
const ageMs = Date.now() - createdAt;
if (ageMs
redis.set(key, JSON.stringify({ value: v, createdAt: Date.now() }), "EX", staleSec),
);
return value;
}
}
const value = await fetcher();
await redis.set(key, JSON.stringify({ value, createdAt: Date.now() }), "EX", staleSec);
return value;
}
HTTP cache headers in Express/Hono
// Immutable assets (hashed filenames)
app.use("/assets", (_, res, next) => {
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
next();
});
// API responses — short cache with revalidation
app.get("/api/products", (_, res) => {
res.setHeader("Cache-Control", "public, max-age=60, stale-while-revalidate=300");
res.json(products);
});
TanStack Query cache configuration
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // Data fresh for 5 minutes
gcTime: 30 * 60 * 1000, // Garbage-collect after 30 minutes
retry: 2,
refetchOnWindowFocus: false,
},
},
});
// Usage in a component
const { data } = useQuery({
queryKey: ["products", { page, category }], // Cache key includes params
queryFn: () => fetchProducts({ page, category }),
});
ANTI_PATTERNS
- Cache-and-forget — Caching data with no invalidation strategy. Data goes stale permanently.
- Instead: define explicit invalidation (event-driven on write, or bounded TTL) for every cache key.
- Uniform TTL — Using the same TTL (e.g., 1 hour) for all data regardless of volatility.
- Instead: match TTL to data change frequency — seconds for prices, minutes for profiles, hours for configs.
- Missing key parameters — Cache key omits user ID, locale, or query params, serving wrong data.
- Instead: include every parameter that affects the result:
products:list:page=2:locale=en.
- Caching errors — Storing error responses (500s, timeouts) with long TTLs.
- Instead: skip caching on failure, or use a very short TTL (5-10 seconds) to allow fast retry.
- Cache stampede — All instances hit the origin simultaneously when a popular key expires.
- Instead: use stale-while-revalidate, jittered TTLs, or a mutex lock to let one instance refresh.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: zebbern
- Source: zebbern/claude-code-guide
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.