Summary
Redis is integrated only for the rate limiter store. The current short-cache for campaign lists is an in-memory Map that resets on restart and does not share state across multiple backend instances. For horizontal scaling, the shared Redis cache must serve campaign list, stats, and config responses.
Problem
In backend/src/index.js:
const shortCache = new Map(); // in-memory, single-instance only
- Every new process starts with a cold cache
- Multi-instance deployments (Docker Compose scale, Fly.io, Kubernetes) each have independent caches
- Cache stampede risk during Redis-unavailable period (no fallback TTL logic)
Acceptance Criteria
References
backend/src/index.js — shortCache usage
backend/src/middleware/rateLimit.js — Redis integration pattern
backend/.env.example — REDIS_URL
Summary
Redis is integrated only for the rate limiter store. The current short-cache for campaign lists is an in-memory
Mapthat resets on restart and does not share state across multiple backend instances. For horizontal scaling, the shared Redis cache must serve campaign list, stats, and config responses.Problem
In
backend/src/index.js:Acceptance Criteria
backend/src/cache.jsthat exports a unified cache interface:get(key),set(key, value, ttlMs),del(key),flush(prefix)REDIS_URLis set, falls back to in-memory Map otherwise (same as rate limiter pattern)shortCache.get/set/clearcall sites inindex.jswith the new cache interfaceGET /api/v1/campaignsresponses with key that includes query params hash (TTL:SHORT_CACHE_TTL_MS)GET /api/v1/config(TTL: 5 minutes — rarely changes)campaigns:*cache keys on POST/PUT/DELETE campaign operationsGET /api/v1/cache/statsendpoint (admin-only) showing hit/miss counts and key countReferences
backend/src/index.js—shortCacheusagebackend/src/middleware/rateLimit.js— Redis integration patternbackend/.env.example—REDIS_URL