Daniel Cohen·
Stampede protection saved us - cache-aside plus probabilistic refresh, no more dogpiles
Implements a complete caching strategy with cache-aside, write-through, invalidation, and stampede protection.
Multi-Layer Caching Strategy Implementer
You are a performance engineer implementing a production caching layer. Design and build the complete system.
## Caching Requirements
- Cache provider: {{cache_provider}} (Redis, Memcached, in-memory, multi-tier)
- Application: {{application_type}}
- Language: {{programming_language}}
- Hot data: {{hot_data_description}}
## Architecture Requirements
1. **Cache Client** - Typed wrapper around {{cache_provider}} with:
- Connection pooling and health checks
- Serialization/deserialization (JSON, MessagePack, or protobuf)
- Key namespacing and versioning
- TTL management with jitter
2. **Cache Strategies** - Implement these patterns:
- Cache-Aside (lazy loading)
- Write-Through (immediate consistency)
- Write-Behind (async durability, if applicable)
- Refresh-Ahead (proactive refresh before expiry)
3. **Stampede Protection** - Dog-piling prevention using locks/probabilistic early refresh
4. **Cache Key Builder** - Type-safe key construction preventing collisions
5. **Invalidation Logic** - Tag-based and pattern-based invalidation
6. **Circuit Breaker** - Fallback to origin on cache failure
7. **Metrics** - Hit/miss ratio, latency, evictions tracking
8. **Serialization** - Efficient serialization with schema versioning
9. **Multi-Tier** - L1 (in-memory) → L2 (Redis) → Origin if configured
10. **Decorator/Aspect** - @Cacheable, @CacheEvict, @CachePut decorators
## Output
1. Complete cache implementation
2. Usage examples for each strategy
3. Cache topology diagram (ASCII)
4. Configuration with sensible defaults
5. Invalidation flow documentation
6. Unit tests with mocked cache provider
Ergebnisse
Caching layer for a product-catalog API in TypeScript over Redis. Cache-aside with stampede protection and tag invalidation.
```typescript
export class Cache {
constructor(private redis: Redis) {}
/** Cache-aside read with probabilistic early refresh (XFetch) to avoid dogpiles. */
async getOrLoad<T>(key: string, ttlMs: number, load: () => Promise<T>): Promise<T> {
const raw = await this.redis.get(key);
if (raw) {
const { v, exp, delta } = JSON.parse(raw);
const early = Date.now() - delta * Math.log(Math.random()) >= exp;
if (!early) return v as T; // serve cached
}
// single-flight: only one caller rebuilds
const lock = await this.redis.set(`${key}:lock`, "1", "PX", 5000, "NX");
if (!lock) return raw ? JSON.parse(raw).v : load(); // others serve stale
const start = Date.now();
const value = await load();
const delta = Date.now() - start;
await this.redis.set(
key,
JSON.stringify({ v: value, exp: Date.now() + ttlMs, delta }),
"PX", ttlMs + delta,
);
return value;
}
}
```
## Topology
```
request ─▶ L1 (in-proc Map) ─miss─▶ L2 (Redis) ─miss─▶ Postgres origin
```
**Invalidation:** `await cache.invalidateTag("product:42")` drops every key tagged with that product. **Defaults:** 5-min TTL with `delta`-scaled jitter so keys don't all expire together. Falls back to the origin if Redis is unreachable.
Modell: Claude Sonnet 4
114 Likes42 SavesScore: 68
5 Kommentare
Lena Fischer·
The diff summary format is so much easier to scan than a wall of code.
Ryan Mitchell·
Our junior devs are going to live on this one.
Priya Nair·
Nice. The schema validation up front prevents a whole class of bugs.
Jonas Weber·
Quietly excellent. No fluff, just the code that works.
Marco Rossi·
Adopted this pattern across three services this week. Zero regressions.