Instruction file imported from Dev-Devarsh/BE-node-microservice-boilerplate (
.cursor/rules/redis-and-caching.mdc). Copyright stays with the author.
Redis & Caching Conventions
Redis client lives at src/infrastructure/redis/. Import the singleton cacheService:
import { cacheService } from '../../../infrastructure/redis/index.js';
Cache-Aside pattern (in Services)
async getById(id: string): Promise<IEntity> {
const cached = await cacheService.get<IEntity>('namespace', id);
if (cached != null) return cached;
const entity = await this.repository.findById(id);
if (entity == null) throw new NotFoundError();
await cacheService.set('namespace', id, entity, 300); // 5 min TTL
return entity;
}
Rules
- Every
cacheService.set()MUST have an explicit TTL — no infinite caching - Invalidate on writes:
cacheService.invalidate('namespace', id) - Bulk invalidate:
cacheService.invalidatePattern('namespace')clears allnamespace:*keys - Redis is optional — all methods return
null/falsewhen Redis is down, code falls through to MongoDB - Namespace pattern:
user:123,user:list:1:20:all,user:analytics:retention:...
TTL guidelines
| Data type | TTL | Constant name pattern |
|---|---|---|
| Single entity | 5 min (300s) | CACHE_TTL_SECONDS |
| Paginated lists | 1 min (60s) | CACHE_TTL_LIST_SECONDS |
| Analytics/aggregations | 15 min (900s) | CACHE_TTL_ANALYTICS_SECONDS |
Token blacklist (in infrastructure/redis/token-blacklist.service.ts)
blacklistToken(token)— on logout, TTL = remaining token lifetimerevokeAllUserTokens(userId)— on password change, invalidates ALL tokens viaiatcheckisTokenBlacklisted(token)+isTokenRevokedForUser(userId, iat)— checked inauth.middleware.ts