This document describes the caching strategy and cache invalidation patterns used across the Brain-Storm backend.
Cache keys follow a hierarchical pattern to enable efficient prefix-based invalidation:
cache_type:resource_type:resource_id[:sub_resource]
Examples:
course:detail:uuid- Single course detailscourse:list:page:0- Course listing pageprogress:user-uuid:course-uuid- User progress per courseinstructor:analytics:instructor-uuid:month- Instructor monthly analytics
| Resource | TTL | Strategy |
|---|---|---|
| Course Details | 1 hour | Long-lived, invalidated on update |
| Course List | 30 minutes | Medium TTL for browsing |
| Enrollment Status | 15 minutes | Dynamic content with moderate TTL |
| User Progress | 10 minutes | Frequently changing, shorter TTL |
| Cohort Members | 5 minutes | Real-time sensitive |
| Leaderboard | 30 minutes | Aggregated, moderate staleness acceptable |
| Instructor Analytics | 1 hour | Heavy computation, long TTL |
Cache is invalidated on the following events:
course.created→ Invalidate course listcourse.updated→ Invalidate course detail + listcourse.deleted→ Invalidate course detail + list
enrollment.created→ Invalidate user progress + course listenrollment.updated→ Invalidate enrollment status + analyticsenrollment.completed→ Invalidate user progress + leaderboard + analytics
progress.recorded→ Invalidate user progress + leaderboardprogress.updated→ Invalidate cohort members cache
Invalidate specific resources:
// Invalidate by key
await this.cacheInvalidation.invalidateByKey(`course:detail:${courseId}`);
// Invalidate by prefix (all matching patterns)
await this.cacheInvalidation.invalidateByPrefix('course:');
// Convenience methods for common resources
await this.cacheInvalidation.invalidateCourse(courseId);
await this.cacheInvalidation.invalidateUserProgress(userId);
await this.cacheInvalidation.invalidateInstructorAnalytics(instructorId);Use jittered TTLs to prevent thundering herd:
const ttl = this.cacheInvalidation.getTtlWithJitter(3600, 10); // ±10% jitterMonitor cache performance with Prometheus:
cache_hits_total- Total cache hits by key prefixcache_misses_total- Total cache misses by key prefix- Hit ratio = hits / (hits + misses)
- Always use prefix patterns when invalidating related data
- Avoid high-cardinality keys - use aggregation/bucketing for metrics
- Monitor hit ratios - maintain >70% for frequently accessed resources
- Use jitter for TTLs on heavy computation results
- Invalidate early - on write operations, not expiration
- Document cache dependencies - track what invalidates what
- Distributed cache invalidation via Redis pub/sub
- Automatic cache warming for popular resources
- Cache size limits and eviction policies
- Cache versioning for blue-green deployments