Deferred from the architecture review (architectural observation #2) — see ARCHITECTURE_REVIEW.md.
Problem
ZigguratModule is single-cache by construction: one global module, one CACHE_MANAGER token, one CacheManager. Both forRoot and forRootAsync register global: true unconditionally (packages/nestjs/src/ziggurat.module.ts).
Real applications usually want several caches with different shapes — users in memory+Redis with a 30s L1, reports in SQLite with an hour TTL, sessions somewhere else entirely. Today that means hand-rolling providers and tokens per cache and bypassing the module, which is the boilerplate this package exists to remove.
The core supports it fine: CacheManager already takes a namespace and its own layer stack. It is only the Nest binding that assumes one.
Sketch
ZigguratModule.forFeature(name, options) returning a scoped provider under a derived token.
- An
@InjectCache(name) decorator, or an exported getCacheToken(name) for manual @Inject.
@Cached({ cache: name, ... }) so the decorator can target a named cache; it currently hardcodes CACHE_MANAGER (packages/nestjs/src/cached.decorator.ts).
forRoot/forRootAsync keep working unchanged as the default/unnamed cache.
Worth deciding as part of this: whether global: true should stay unconditional. A forFeature cache scoped to the module that declared it is the more Nest-idiomatic default, and a global escape hatch can be opt-in.
Done when
An app can register two independently configured caches, inject either one by name, and point @Cached() at a specific one — without writing custom providers.
Deferred from the architecture review (architectural observation #2) — see
ARCHITECTURE_REVIEW.md.Problem
ZigguratModuleis single-cache by construction: one global module, oneCACHE_MANAGERtoken, oneCacheManager. BothforRootandforRootAsyncregisterglobal: trueunconditionally (packages/nestjs/src/ziggurat.module.ts).Real applications usually want several caches with different shapes —
usersin memory+Redis with a 30s L1,reportsin SQLite with an hour TTL,sessionssomewhere else entirely. Today that means hand-rolling providers and tokens per cache and bypassing the module, which is the boilerplate this package exists to remove.The core supports it fine:
CacheManageralready takes anamespaceand its own layer stack. It is only the Nest binding that assumes one.Sketch
ZigguratModule.forFeature(name, options)returning a scoped provider under a derived token.@InjectCache(name)decorator, or an exportedgetCacheToken(name)for manual@Inject.@Cached({ cache: name, ... })so the decorator can target a named cache; it currently hardcodesCACHE_MANAGER(packages/nestjs/src/cached.decorator.ts).forRoot/forRootAsynckeep working unchanged as the default/unnamed cache.Worth deciding as part of this: whether
global: trueshould stay unconditional. AforFeaturecache scoped to the module that declared it is the more Nest-idiomatic default, and a global escape hatch can be opt-in.Done when
An app can register two independently configured caches, inject either one by name, and point
@Cached()at a specific one — without writing custom providers.