Cache Documentation
This documentation explains the features and usage of:
- Cache Module: Located at
src/common/cache - Redis Module: Located at
src/common/redis
Overview
This application uses Redis as the cache storage backend to improve performance and reduce database load. The cache is implemented using a global module pattern, making it accessible throughout the application without repeated imports.
This application uses cache-manager v6 which migrated to Keyv as the unified storage interface. We use @keyv/redis as the Redis adapter.
Related Documents
- Configuration Documentation - For Redis configuration settings
- Environment Documentation - For Redis environment variables
- Authentication Documentation - For session cache usage examples
- Response Documentation - For response caching implementation
Table of Contents
Principles & Patterns
DRY & Singleton Pattern
- Single Redis Connection: Only ONE Redis connection created and shared across all services
- Single Configuration: Defined once in
redis.config.ts - Reusable Providers:
CacheMainProviderandSessionCacheProvidershare the same Redis client
Example:
❌ Without DRY:
UserService → Creates Redis connection 1
ProductService → Creates Redis connection 2
OrderService → Creates Redis connection 3
✅ With DRY:
RedisCacheModule → Creates ONE Redis connection
All services → Inject and reuse the same connectionGlobal Module Pattern
RedisCacheModule and CacheMainModule are marked as @Global():
- Providers automatically available everywhere
- No need to import in feature modules
Architecture
Module Dependency Flow
CommonModule
├── RedisCacheModule (Global)
│ └── Creates: RedisClientCachedProvider
│
├── CacheMainModule (Global)
│ └── Uses: RedisClientCachedProvider
│ └── Provides: CacheMainProvider
│
└── SessionModule
└── Uses: RedisClientCachedProvider
└── Provides: SessionCacheProvider (Scoped)RedisCacheModule
Purpose: Provides Redis client instance
Provider: RedisClientCachedProvider
Scope: Global (available everywhere)
Configuration:
createKeyv(
{ url: 'redis://localhost:6379' },
{
connectionTimeout: 30000,
namespace: 'Cache',
useUnlink: true,
keyPrefixSeparator: ':'
}
)CacheMainModule
Purpose: Provides cache manager for application-wide caching
Provider: CacheMainProvider
Scope: Global (available everywhere)
Depends on: RedisClientCachedProvider
Usage:
export class UserService {
constructor(
@Inject(CacheMainProvider) readonly cache: Cache,
) {}
}SessionModule
Purpose: Provides cache for session management only
Provider: SessionCacheProvider
Scope: Module-scoped (only within SessionModule)
Depends on: RedisClientCachedProvider (shares same Redis connection)
Usage:
export class SessionService {
constructor(
@Inject(SessionCacheProvider) private cache: Cache,
) {}
}Why Scoped?
- Sessions are domain-specific
- Prevents accidental usage outside session context
- Still uses shared Redis connection (resource efficient)
Configuration
Redis Configuration
File: src/configs/redis.config.ts
{
cache: {
url: process.env.CACHE_REDIS_URL ?? 'redis://localhost:6379',
namespace: 'Cache',
ttlInMs: 5 * 60 * 1000 // Default TTL: 5 minutes
}
}Default TTL: Cache entries expire after 5 minutes (300,000 milliseconds) by default. This can be overridden per cache operation.
Module Import Order
File: src/common/common.module.ts
@Module({
imports: [
ConfigModule.forRoot(),
RedisCacheModule.forRoot(), // 1. First
CacheMainModule.forRoot(), // 2. Second
SessionModule, // 3. Then feature modules
]
})
export class CommonModule {}Why this order? CacheMainModule depends on RedisClientCachedProvider from RedisCacheModule.
Usage
Injecting Cache Providers
Global cache:
@Injectable()
export class UserService {
constructor(
@Inject(CacheMainProvider) readonly cache: Cache,
) {}
}Session cache:
@Injectable()
export class SessionService {
constructor(
@Inject(SessionCacheProvider) private cache: Cache,
) {}
}Cache Operations
For cache operations (set, get, delete, etc.), see:
- [NestJS Caching][ref-nestjs-caching]
- [cache-manager][ref-cache-manager]