or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/cache-manager@7.2.x

docs

index.md
tile.json

tessl/npm-cache-manager

tessl install tessl/npm-cache-manager@7.2.0

Cache Manager for Node.js with support for multi-store caching, background refresh, and Keyv-compatible storage adapters

configuration.mddocs/reference/

Configuration Reference

Complete reference for all cache-manager configuration options.

CreateCacheOptions

type CreateCacheOptions = {
  stores?: Keyv[];
  ttl?: number;
  refreshThreshold?: number;
  refreshAllStores?: boolean;
  nonBlocking?: boolean;
  cacheId?: string;
};

stores

Type: Keyv[]
Default: [new Keyv()] (in-memory)
Description: Array of Keyv store instances in priority order (first = highest priority)

Example:

import { Keyv } from 'keyv';
import KeyvRedis from '@keyv/redis';
import { CacheableMemory } from 'cacheable';

const cache = createCache({
  stores: [
    new Keyv({ store: new CacheableMemory({ lruSize: 1000 }) }),
    new Keyv({ store: new KeyvRedis('redis://localhost:6379') }),
  ],
});

Behavior:

  • Read: Searches stores in order, returns first match
  • Write: Writes to all stores (unless nonBlocking)
  • Empty array: Falls back to default in-memory store

ttl

Type: number
Default: undefined (depends on store)
Unit: Milliseconds
Description: Default time-to-live for all cache entries

Example:

const cache = createCache({
  ttl: 300000, // 5 minutes default
});

await cache.set('key', 'value'); // Uses 300000ms TTL
await cache.set('other', 'value', 60000); // Overrides with 60000ms

Notes:

  • Can be overridden per-operation
  • 0 or negative values cause immediate expiration
  • Infinity may mean no expiration (store-dependent)
  • If not set, depends on store's default behavior

refreshThreshold

Type: number
Default: undefined (no automatic refresh)
Unit: Milliseconds
Description: Triggers background refresh when remaining TTL falls below this value

Example:

const cache = createCache({
  ttl: 300000,           // 5 minutes total
  refreshThreshold: 60000 // Refresh when < 1 minute remains
});

Requirements:

  • Must be less than ttl
  • Only works with wrap() method
  • Requires TTL to be set

Behavior:

TTL: 300000ms (5 minutes)
Threshold: 60000ms (1 minute)

Time 0s:   Entry created
Time 4m:   Remaining: 60s (equal to threshold)
Time 4m1s: wrap() called → returns cached, triggers background refresh

refreshAllStores

Type: boolean
Default: false
Description: Controls which stores are updated during background refresh

Example:

const cache = createCache({
  stores: [memoryStore, redisStore],
  refreshAllStores: false, // Default
});

Behavior:

With refreshAllStores: false (default):

  • Key in L1 → Refresh L1 only
  • Key in L2 → Refresh L1 and L2
  • Reduces write amplification

With refreshAllStores: true:

  • Always refreshes all stores
  • Ensures consistency across all tiers
  • Higher write load

Use Cases:

  • false: Performance-critical, eventual consistency OK
  • true: Strong consistency required across all stores

nonBlocking

Type: boolean
Default: false
Description: Enables non-blocking mode for multi-store operations

Example:

const cache = createCache({
  stores: [fastStore, slowStore],
  nonBlocking: true,
});

Behavior:

With nonBlocking: false (default):

  • Get: Waits for all stores, returns first match
  • Set: Waits for all stores to complete
  • Delete: Waits for all stores to complete
  • Guarantees: Strong consistency

With nonBlocking: true:

  • Get: Uses Promise.race(), returns fastest result
  • Set: Returns after first store succeeds
  • Delete: Returns after first store succeeds
  • Trade-off: Better performance, eventual consistency

Performance Impact:

// Blocking (default)
await cache.set('key', 'value'); // Waits: ~50ms (slowest store)

// Non-blocking
await cache.set('key', 'value'); // Waits: ~1ms (fastest store)

cacheId

Type: string
Default: Auto-generated unique ID
Description: Unique identifier for this cache instance

Example:

const cache1 = createCache({ cacheId: 'user-cache' });
const cache2 = createCache({ cacheId: 'product-cache' });

console.log(cache1.cacheId()); // 'user-cache'
console.log(cache2.cacheId()); // 'product-cache'

Purpose:

  • Internal use for wrap() coalescing
  • Prevents conflicts between multiple cache instances
  • Useful for debugging and monitoring

Keyv Options

When creating Keyv instances, you can configure store-specific options:

interface KeyvOptions {
  store?: any;              // Storage adapter instance
  namespace?: string;       // Key prefix namespace
  ttl?: number;            // Default TTL for this store
  serialize?: (data: any) => string;
  deserialize?: (data: string) => any;
  compression?: any;        // Compression adapter
}

Example Keyv Configuration

import { Keyv } from 'keyv';
import KeyvRedis from '@keyv/redis';
import msgpack from 'msgpack';

const keyv = new Keyv({
  store: new KeyvRedis('redis://localhost:6379'),
  namespace: 'myapp',
  ttl: 3600000, // 1 hour default for this store
  serialize: msgpack.encode,
  deserialize: msgpack.decode,
});

const cache = createCache({
  stores: [keyv],
});

Store-Specific Configuration

CacheableMemory Options

import { CacheableMemory } from 'cacheable';

new CacheableMemory({
  ttl: 60000,      // Default TTL in milliseconds
  lruSize: 1000,   // Maximum number of items (LRU eviction)
  useClone: false  // Clone values on get/set (default: false)
})

KeyvRedis Options

import KeyvRedis from '@keyv/redis';

new KeyvRedis('redis://localhost:6379', {
  // ioredis options
  password: 'secret',
  db: 0,
  keyPrefix: 'cache:',
  lazyConnect: false,
  enableOfflineQueue: true,
  maxRetriesPerRequest: 3,
})

Configuration Patterns

Development Configuration

const cache = createCache({
  stores: [
    new Keyv({
      store: new CacheableMemory({ 
        lruSize: 100, // Small cache
        ttl: 10000    // Short TTL for testing
      }),
    }),
  ],
  ttl: 10000,
});

Production Configuration

const cache = createCache({
  stores: [
    // L1: Fast memory cache
    new Keyv({
      store: new CacheableMemory({ 
        ttl: 60000,       // 1 minute
        lruSize: 5000     // 5000 hot items
      }),
    }),
    // L2: Shared Redis cache
    new Keyv({
      store: new KeyvRedis(process.env.REDIS_URL!, {
        password: process.env.REDIS_PASSWORD,
        db: 0,
        lazyConnect: false,
        maxRetriesPerRequest: 3,
      }),
      ttl: 3600000,       // 1 hour
    }),
  ],
  ttl: 300000,            // 5 minutes default
  refreshThreshold: 60000, // Refresh at 1 minute
  refreshAllStores: true,  // Ensure consistency
  nonBlocking: false,      // Strong consistency
  cacheId: 'main-cache',
});

High-Performance Configuration

const cache = createCache({
  stores: [
    new Keyv({
      store: new CacheableMemory({ 
        lruSize: 10000,  // Large cache
        ttl: 120000      // 2 minutes
      }),
    }),
    new Keyv({
      store: new KeyvRedis(redisUrl),
    }),
  ],
  nonBlocking: true,       // Fast returns
  refreshAllStores: false, // Reduce writes
});

Environment-Based Configuration

import { createCache } from 'cache-manager';

function createAppCache() {
  const isDev = process.env.NODE_ENV === 'development';
  const isTest = process.env.NODE_ENV === 'test';
  
  if (isTest) {
    // In-memory only for tests
    return createCache({
      stores: [new Keyv()],
      ttl: 1000, // Short TTL
    });
  }
  
  if (isDev) {
    // Simple setup for development
    return createCache({
      stores: [
        new Keyv({ 
          store: new CacheableMemory({ lruSize: 100 })
        }),
      ],
      ttl: 60000,
    });
  }
  
  // Production: multi-tier with Redis
  return createCache({
    stores: [
      new Keyv({ 
        store: new CacheableMemory({ 
          lruSize: parseInt(process.env.CACHE_SIZE || '5000'),
          ttl: 60000 
        })
      }),
      new Keyv({ 
        store: new KeyvRedis(process.env.REDIS_URL!),
        ttl: 3600000
      }),
    ],
    ttl: parseInt(process.env.CACHE_TTL || '300000'),
    refreshThreshold: parseInt(process.env.CACHE_REFRESH_THRESHOLD || '60000'),
    refreshAllStores: process.env.CACHE_REFRESH_ALL === 'true',
  });
}

export const cache = createAppCache();

Configuration Validation

function validateCacheConfig(options: CreateCacheOptions) {
  if (options.refreshThreshold && options.ttl) {
    if (options.refreshThreshold >= options.ttl) {
      throw new Error('refreshThreshold must be less than ttl');
    }
  }
  
  if (options.stores && options.stores.length === 0) {
    console.warn('Empty stores array, using default in-memory store');
  }
  
  if (options.ttl && options.ttl <= 0) {
    console.warn('TTL <= 0 will cause immediate expiration');
  }
}

// Usage
const config: CreateCacheOptions = {
  ttl: 300000,
  refreshThreshold: 60000,
};

validateCacheConfig(config);
const cache = createCache(config);

Performance Tuning

Memory Budget Calculation

function calculateOptimalLruSize(
  memoryBudgetMB: number,
  avgItemSizeKB: number
): number {
  const memoryBudgetBytes = memoryBudgetMB * 1024 * 1024;
  const avgItemSizeBytes = avgItemSizeKB * 1024;
  return Math.floor(memoryBudgetBytes / avgItemSizeBytes);
}

const lruSize = calculateOptimalLruSize(50, 1); // 50MB / 1KB = ~50,000 items

const cache = createCache({
  stores: [
    new Keyv({
      store: new CacheableMemory({ lruSize }),
    }),
  ],
});

TTL Strategy

const TTL_STRATEGY = {
  // Critical data: short TTL, frequent refresh
  critical: { ttl: 60000, refreshThreshold: 20000 },
  
  // Hot data: medium TTL
  hot: { ttl: 300000, refreshThreshold: 60000 },
  
  // Warm data: long TTL
  warm: { ttl: 1800000, refreshThreshold: 300000 },
  
  // Cold data: very long TTL
  cold: { ttl: 86400000, refreshThreshold: 7200000 },
};

// Apply based on data type
await cache.wrap(
  'critical:config',
  fetchConfig,
  TTL_STRATEGY.critical.ttl,
  TTL_STRATEGY.critical.refreshThreshold
);

Next Steps

  • Type Definitions Reference - All types
  • Core Operations Reference - API usage
  • Troubleshooting - Common configuration issues