# 07. Caching Strategy (Redis + HTTP Cache) meta: id: web-production-07 feature: web-production priority: P2 depends_on: [] tags: [performance, caching, production] objective: - Implement multi-layer caching to reduce database load and improve response times deliverables: - Redis caching layer for API responses - HTTP cache headers for client-side caching - Cache invalidation strategy - Stale-while-revalidate pattern steps: 1. Implement Redis caching for API responses: - Create web/src/server/lib/cache.ts with Redis-backed cache - Cache user profile: key `user:{id}`, TTL 5 minutes - Cache subscription: key `sub:{userId}`, TTL 1 minute - Cache dashboard summary: key `dash:{userId}`, TTL 30 seconds - Cache blog posts: key `blog:{slug}`, TTL 1 hour 2. Add cache decorators/procedures: - Create cachedProcedure wrapper for tRPC - Support cache tags for invalidation 3. Implement HTTP caching headers: - Static assets: Cache-Control: public, max-age=31536000, immutable - API responses: Cache-Control: private, max-age=30 - HTML pages: Cache-Control: no-cache (SSR) 4. Add cache invalidation: - Invalidate user cache on profile update - Invalidate subscription cache on billing event - Invalidate blog cache on publish/edit 5. Implement stale-while-revalidate for dashboard data 6. Add cache hit/miss metrics tests: - Unit: Test cache set/get/delete operations - Integration: Test cache invalidation on mutations - Performance: Compare cached vs uncached response times acceptance_criteria: - Redis cache layer active on all read-heavy endpoints - Cache hit rate >80% for user profile and subscription endpoints - Cache invalidation working on all mutations - HTTP cache headers correct per endpoint type - Stale-while-revalidate pattern on dashboard widgets - Cache metrics visible in monitoring dashboard validation: - Load test: cached endpoint p95 < 20ms - Verify Redis keys created for cached data - Update profile → cache invalidated, next request hits DB notes: - Redis already used for BullMQ jobs — share connection or use separate DB index - Be careful caching authenticated data — always include userId in key - Consider using Vercel KV or Upstash Redis for serverless