cache-registry
v5.0.0
Published
Cache registry class to facilitate caching withing application. using singleton pattern to ensure usage of same instance. Must important feature is to get/set cache in one go using callback functions
Readme
Cache Registry
A minimalistic, framework-agnostic caching utility for Node.js applications. Supports both in-memory and Redis-based caching with a simple, unified API.
Table of Contents
- Features
- Installation
- Quick Start
- Examples
- Usage
- Recommended Setup
- Multiple Cache Instances
- How Instance Management Works
- API Reference
- Best Practices
- FAQ
- License
Features
- In-memory and Redis cache support
- Singleton instance management: Identical options return the same instance
- Shared Redis connection: All cache instances using Redis, share a single connection
- TypeScript support
- Framework agnostic
- Graceful error handling: Cache failures never break your app
Installation
npm install cache-registryQuick Start
TCacheInputOptions
The TCacheInputOptions type defines the configuration options for initializing a cache registry instance. These options let you control the cache type, expiration, key management, and whether caching is enabled/disabled making it easy to tailor caching behavior for different environments (e.g., disabling cache in local development to test new features).
type TCacheInputOptions = IInMemoryCacheOptions | IRedisCacheOptions;
interface IInMemoryCacheOptions {
/**
* The cache backend type: 'in-memory'.
*/
type: CacheTypeEnum.IN_MEMORY;
/**
* Default time-to-live (TTL) for cached items, in seconds.
*/
cacheTtl: number;
/**
* Enable or disable caching. Useful for turning off cache in development or testing environments.
*/
isCacheEnable: boolean;
/**
* (Optional) Prefix to add to all cache keys.
*/
keyPrefix?: string;
}
interface IRedisCacheOptions {
/**
* The cache backend type: 'redis'.
*/
type: CacheTypeEnum.REDIS;
/**
* Default time-to-live (TTL) for cached items, in seconds.
*/
cacheTtl: number;
/**
* Enable or disable caching. Useful for turning off cache in development or testing environments.
*/
isCacheEnable: boolean;
/**
* Required prefix to add to all cache keys. Mandatory for Redis to avoid key collisions.
*/
keyPrefix: string;
/**
* Redis connection options.
*/
redisOptions: RedisClientOptions;
}Usage tip:
- Set
isCacheEnable: falsein your local.envor configuration to disable caching during development, ensuring you always fetch fresh data while testing new features. In production, setisCacheEnable: truefor optimal performance.
Examples
Comprehensive examples demonstrating common patterns are available in the examples/ directory:
- Basic Usage - Core operations: get, set, delete, clear
- Lazy Caching - Cache-aside pattern with automatic fallback
- Multiple Instances - Managing different cache configurations
- Redis Resilience - Production-ready Redis with auto-reconnection
- Environment Config - Switching backends by environment
Run examples:
npm run build
npx tsx examples/01-basic-usage.tsSee the examples README for detailed documentation.
Usage
In-Memory Cache Example
import { getCacheRegistry, CacheTypeEnum } from 'cache-registry';
// Initialize cache
function initCache() {
const cache = getCacheRegistry({
type: CacheTypeEnum.IN_MEMORY,
isCacheEnable: true,
cacheTtl: 60, // seconds
});
return cache;
}Redis Cache Example
import { getCacheRegistry, CacheTypeEnum } from 'cache-registry';
function initCache() {
const cache = getCacheRegistry({
type: CacheTypeEnum.REDIS,
isCacheEnable: true,
cacheTtl: 120,
keyPrefix: 'myapp',
redisOptions: { url: 'redis://localhost:6379' }, // Standard redis client options
});
return cache;
}Recommended Setup
To avoid repeated configuration, initialize and export your cache instance from a utility/provider module:
// utils/cache.ts
import { getCacheRegistry, CacheTypeEnum } from 'cache-registry';
export const cache = getCacheRegistry({
type: CacheTypeEnum.IN_MEMORY,
isCacheEnable: process.env.CACHE_ENABLE === 'yes',
cacheTtl: process.env.CACHE_EXPIRATION ? parseInt(process.env.CACHE_EXPIRATION) : 60,
});Then, use your cache instance anywhere in your application:
import { cache } from './utils/cache';
async function getColor() {
return await cache.get('color');
}
async function setColor(colors: string[]) {
await cache.set('color', colors);
}Multiple Cache Instances
You can create multiple cache instances for different data lifecycles (e.g., short TTL for DB data, long TTL for API responses):
import { getCacheRegistry, CacheTypeEnum } from 'cache-registry';
const dbCache = getCacheRegistry({
type: CacheTypeEnum.IN_MEMORY,
isCacheEnable: true,
cacheTtl: 60, // 1 minute
});
const httpCache = getCacheRegistry({
type: CacheTypeEnum.IN_MEMORY,
isCacheEnable: true,
cacheTtl: 3600, // 1 hour
});How Instance Management Works
getCacheRegistry(options) returns the same instance for identical options. Internally, a Map keyed on type + cacheTtl + keyPrefix + isCacheEnable + redisUrl ensures singleton behavior.
- type:
CacheTypeEnum.IN_MEMORYorCacheTypeEnum.REDIS - cacheTtl: Time-to-live in seconds
- keyPrefix: (optional for in-memory, required for Redis) Prefix for all cache keys
- isCacheEnable: Included in the key — different enable/disable settings produce separate instances
For Redis, all cache registries that connect to the same Redis server (e.g., the same url, such as redis://localhost:6379) will share a single Redis connection. This means you won't have multiple open connections to the same Redis instance, even if you create several cache instances pointing to the same server—helping to reduce resource usage and avoid unnecessary connections.
Connection Resilience
When using Redis, the cache automatically handles connection issues:
- On disconnection: Logs a single error message (avoids log spam during reconnection attempts)
- During downtime: Cache operations gracefully degrade—
get()returns null or executes fallback,set()silently skips caching - On reconnection: Automatically restores connection and resumes caching
- Shared error handling: Multiple cache instances share connection state, so you only see one error log regardless of how many instances you have
API Reference
getCacheRegistry(options: TCacheInputOptions)
Returns a cache registry instance. For identical options, returns the same singleton instance.
Options:
type:CacheTypeEnum.IN_MEMORY|CacheTypeEnum.REDISisCacheEnable:boolean- Enable/disable cachingcacheTtl:number- Time-to-live in secondskeyPrefix:string- Required for Redis, optional for in-memoryredisOptions:RedisClientOptions- Required for Redis. See Redis client options
destroyCacheRegistry(): Promise<void>
Async. Clears all cached registry instances and disconnects the Redis connection. Useful for testing or graceful shutdown. Always await this call.
Instance Methods
get<T>(key: string, fallback?: () => Promise<T>): Promise<T | null>— Retrieve a value by key from the cache.- Without a callback: Returns the cached value if present, or
nullif not found. - With a callback: If the value is not present in the cache, the callback is executed to fetch or compute the value, which is then cached and returned. If the value is already cached, the callback is not executed and the cached value is returned immediately. This allows you to implement a lazy caching pattern (get-or-set) in a single call.
// Only fetches from DB if not cached const data = await cache.get('my-key', async () => { return await db.getExpensiveData(); });- Without a callback: Returns the cached value if present, or
set<T>(key: string, value: T): Promise<void>— Store a value by key in the cache.delete(key: string): Promise<void>— Delete an element from the cache by its key.clear(): Promise<void>— Remove all values from the cache (clear the cache).getKeys(): Promise<string[]>— Return all keys currently stored in this cache registry instance.
Best Practices
- Export a singleton cache instance from a utility module for reuse.
- Use keyPrefix always use key prefix to avoid cache instances collisions specially when using redis.
- Handle cache errors gracefully: Cache Registry is designed not to throw on cache failures.
- Configure TTLs appropriately for different data sources.
FAQ
Q: What happens if Redis is down?
A: Cache operations gracefully degrade—get() returns null/fallback, set() silently skips. Only one error is logged (no spam during retries). The cache automatically reconnects when Redis becomes available again—no manual intervention required.
Q: Can I use this in any Node.js framework?
A: Yes, Cache Registry is framework-agnostic.
License
MIT
