CachingPlugin
Caches responses in memory with configurable time-to-revalidate, precise invalidation, per-request overrides, and a pluggable storage adapter contract for Redis or Memcached.
Install
import { createCachePlugin } from 'axios-retryer/plugins/CachingPlugin'; Basic usage
import { createRetryer, AXIOS_RETRYER_HTTP_METHODS } from 'axios-retryer';
import { createCachePlugin } from 'axios-retryer/plugins/CachingPlugin';
const cache = createCachePlugin({
timeToRevalidate: 60_000, // 1 minute TTR
cacheMethods: [AXIOS_RETRYER_HTTP_METHODS.GET], // Only cache GET
maxItems: 200,
cleanupInterval: 5 * 60_000, // Prune expired entries every 5 min
});
const retryer = createRetryer().use(cache); All options
createCachePlugin({
timeToRevalidate: 60_000, // Cache lifetime in ms (default: 60000)
cacheMethods: ['get'], // HTTP methods to cache (default: ['get'])
maxItems: 100, // Max cached entries; oldest evicted first (default: Infinity)
cleanupInterval: 300_000, // ms between expired-entry pruning (default: 300000)
compareHeaders: false, // Include headers in cache key (default: false)
cacheOnlyRetriedRequests: false, // Only cache responses from retry attempts (default: false)
skipWhenAuthPresent: true, // Don't cache when Authorization header is set (default: true)
// Custom key builder — receives normalized request fields
cacheKeyBuilder: ({ method, normalizedUrl, normalizedParams }) =>
`${method}|${normalizedUrl}|${normalizedParams}`,
// Custom storage adapter (e.g. Redis)
storage: myRedisAdapter,
}) Cache invalidation
// Build a canonical cache key for an exact match
const userKey = cache.buildCacheKey({ method: 'get', url: '/api/users/1' });
// 1. Exact key invalidation
cache.invalidateCache({ exact: userKey });
// 2. Prefix invalidation (all /api/users/* entries)
cache.invalidateCache({ prefix: 'GET|/api/users/' });
// 3. RegExp invalidation
cache.invalidateCache({ pattern: /\/api\/products\/\d+/ });
// 4. Clear everything
cache.clearCache(); Per-request overrides
Override global cache settings for a single request via __cachingOptions:
// Force-cache a POST response
await retryer.axiosInstance.post('/api/summary', payload, {
__cachingOptions: { cache: true, ttr: 30_000 },
});
// Skip caching for a specific GET
await retryer.axiosInstance.get('/api/live-prices', {
__cachingOptions: { cache: false },
});
// Custom TTR for one request
await retryer.axiosInstance.get('/api/config', {
__cachingOptions: { ttr: 300_000 }, // 5 minutes
}); Cache statistics
const stats = cache.getCacheStats();
console.log(stats.size); // Number of entries
console.log(stats.averageAge); // ms since entries were cached on average Custom storage adapter
Implement CacheStorage to back the cache with Redis, Memcached, or any persistent store:
import type {
CacheStorage,
CacheStorageEntry,
CachedItem,
} from 'axios-retryer/plugins/CachingPlugin';
class RedisAdapter implements CacheStorage {
async get(key: string): Promise<CachedItem | undefined> {
const raw = await redis.get(key);
return raw ? JSON.parse(raw) : undefined;
}
async set(key: string, value: CachedItem): Promise<void> {
await redis.set(key, JSON.stringify(value), 'PX', value.expiresAt - Date.now());
}
async delete(key: string): Promise<void> {
await redis.del(key);
}
async clear(): Promise<void> {
await redis.flushDb();
}
async entries(): Promise<readonly CacheStorageEntry[]> {
// Return the index for cleanup, invalidation, and maxItems enforcement
const keys = await redis.keys('*');
return keys.map(key => [key, { /* metadata */ } as CachedItem]);
}
}
const cache = createCachePlugin({ storage: new RedisAdapter() });
const retryer = createRetryer().use(cache); Security notes
Do not share caching instances across users or tenants
Cache keys do not isolate principals by default. In SSR or multi-user server contexts, use separate retryer instances per user, or disable caching for personalized endpoints. The default skipWhenAuthPresent: true is a safety net, not a guarantee.