Runtime Memory Cache
A lightweight, high-performance in-memory cache for Node.js with TTL support, automatic cleanup, memory usage tracking, and zero dependencies.
Fast Performance
O(1) lookups using native JavaScript Map with zero dependencies
TTL Support
Time To Live with automatic expiration and manual cleanup
Eviction Policies
FIFO or LRU eviction with size limiting and skip touch
Statistics Tracking
Optional stats for hits, misses, evictions, and performance
Memory Tracking
Monitor memory usage with estimated bytes per entry
TypeScript
Full type definitions and TypeScript support built-in
🎮 Interactive Playground
Try out the cache features live! Set values, test eviction policies, and monitor statistics in real-time.
Cache Configuration
Set Value
Get / Check / Delete
Cache Operations
Cache Keys (0)
No keys in cache
Statistics
Installation
npm install runtime-memory-cache Quick Start
import RuntimeMemoryCache from 'runtime-memory-cache';
// Create cache with options
const cache = new RuntimeMemoryCache({
ttl: 60000, // 1 minute default TTL
maxSize: 1000, // Maximum 1000 entries
enableStats: true, // Enable statistics tracking
evictionPolicy: 'LRU' // Use LRU eviction policy
});
// Store data
cache.set('user:123', { name: 'John', age: 30 });
// Retrieve data
const user = cache.get('user:123');
console.log(user); // { name: 'John', age: 30 }
// Check if key exists
if (cache.has('user:123')) {
console.log('User exists!');
} Constructor Options
interface CacheOptions {
ttl?: number; // Default TTL in milliseconds
maxSize?: number; // Maximum cache entries (default: 1000)
enableStats?: boolean; // Enable statistics tracking (default: false)
evictionPolicy?: 'FIFO' | 'LRU'; // Eviction policy (default: 'FIFO')
} | Option | Type | Default | Description |
|---|---|---|---|
| ttl | number | undefined | Default TTL for cache entries in milliseconds |
| maxSize | number | 1000 | Maximum number of entries in cache |
| enableStats | boolean | false | Enable statistics tracking |
| evictionPolicy | 'FIFO' | 'LRU' | 'FIFO' | Cache eviction policy |
API Methods
set(key: string, value: any, ttl?: number): void
Store a value with optional TTL override.
cache.set('key', 'value'); // Uses default TTL
cache.set('key', 'value', 30000); // 30 second TTL
cache.set('key', 'value', undefined); // No expiration get(key: string): any
Retrieve a value. Returns undefined if key doesn't exist or has expired.
const value = cache.get('key');
if (value !== undefined) {
console.log('Found:', value);
} has(key: string, skipTouch?: boolean): boolean
Check if key exists and is not expired. Optionally skip updating access time.
💡 Skip Touch Feature
Set skipTouch: true to check existence without affecting LRU order.
// Normal check - updates access time for LRU
if (cache.has('key')) {
console.log('Key exists');
}
// Skip touch - doesn't affect LRU order
if (cache.has('key', true)) {
console.log('Key exists, LRU order unchanged');
} del(key: string): boolean
Delete a specific key. Returns true if key existed.
const wasDeleted = cache.del('key');
if (wasDeleted) {
console.log('Key was deleted');
} size(): number
Get current number of entries in cache.
console.log(`Cache has ${cache.size()} entries`); clear(): void
Remove all entries from cache.
cache.clear();
console.log(cache.size()); // 0 keys(): string[]
Get array of all keys in cache.
const allKeys = cache.keys();
console.log('All keys:', allKeys); cleanup(): number
Manually remove expired entries. Returns number of entries removed.
const removedCount = cache.cleanup();
console.log(`Removed ${removedCount} expired entries`); getStats(): CacheStats | null
Get cache statistics (if enabled).
interface CacheStats {
hits: number; // Cache hits
misses: number; // Cache misses
size: number; // Current cache size
maxSize: number; // Maximum allowed size
evictions: number; // Number of evicted entries
} const stats = cache.getStats();
if (stats) {
console.log(`Hits: ${stats.hits}, Misses: ${stats.misses}`);
console.log(`Hit Rate: ${(stats.hits / (stats.hits + stats.misses) * 100).toFixed(2)}%`);
} resetStats(): void
Reset statistics counters (if enabled).
cache.resetStats();
console.log(cache.getStats()); // All counters reset to 0 getEvictionPolicy(): 'FIFO' | 'LRU'
Get the current eviction policy being used.
console.log(cache.getEvictionPolicy()); // 'FIFO' or 'LRU' getMemoryUsage(): MemoryUsage
Get estimated memory usage of the cache.
interface MemoryUsage {
estimatedBytes: number; // Total estimated bytes
averageBytesPerEntry: number; // Average bytes per entry
} const memInfo = cache.getMemoryUsage();
console.log(`Cache uses ~${memInfo.estimatedBytes} bytes`);
console.log(`Average: ${memInfo.averageBytesPerEntry} bytes per entry`); Eviction Policies
FIFO (First In, First Out) - Default
- Removes the oldest inserted entry first
- Simple and predictable behavior
- Good for time-based caching scenarios
- Tracks access time for consistency
const fifoCache = new RuntimeMemoryCache({
maxSize: 100,
evictionPolicy: 'FIFO'
}); LRU (Least Recently Used)
- Removes the entry that hasn't been accessed for the longest time
- Better cache hit rates for access-pattern-based scenarios
- Uses access time tracking for eviction decisions
-
Updates on
get(),has(), andset() -
Skip Touch: Use
has(key, true)to check without affecting order
const lruCache = new RuntimeMemoryCache({
maxSize: 100,
evictionPolicy: 'LRU'
}); 📝 Both policies:
- Automatically remove entries when cache is full
- Track eviction count in statistics
- Maintain O(1) average performance
- Update access time for consistency
Usage Examples
API Response Caching
const apiCache = new RuntimeMemoryCache({
ttl: 300000, // 5 minutes
maxSize: 1000,
enableStats: true
});
async function fetchUser(userId: string) {
const cacheKey = `user:${userId}`;
// Try cache first
let user = apiCache.get(cacheKey);
if (user) return user;
// Fetch from API and cache
user = await fetch(`/api/users/${userId}`).then(r => r.json());
apiCache.set(cacheKey, user);
return user;
} Session Management
const sessionCache = new RuntimeMemoryCache({
ttl: 1800000, // 30 minutes
maxSize: 10000
});
function createSession(userId: string, data: any): string {
const sessionId = generateId();
sessionCache.set(`session:${sessionId}`, { userId, ...data });
return sessionId;
}
function getSession(sessionId: string) {
return sessionCache.get(`session:${sessionId}`);
} Rate Limiting
const rateLimiter = new RuntimeMemoryCache({ ttl: 60000 }); // 1 minute window
function checkRateLimit(clientId: string, maxRequests: number = 100): boolean {
const key = `rate:${clientId}`;
const current = rateLimiter.get(key) || 0;
if (current >= maxRequests) {
return false; // Rate limit exceeded
}
rateLimiter.set(key, current + 1);
return true;
} Skip Touch Feature with LRU Cache
const lruCache = new RuntimeMemoryCache({
maxSize: 3,
evictionPolicy: 'LRU',
enableStats: true
});
// Fill cache to capacity
lruCache.set('user:1', 'Alice');
lruCache.set('user:2', 'Bob');
lruCache.set('user:3', 'Charlie');
// Check existence without affecting LRU order
if (lruCache.has('user:1', true)) {
console.log('User 1 exists, but LRU order unchanged');
}
// Normal check that updates LRU order
if (lruCache.has('user:2')) {
console.log('User 2 exists and moved to most recent');
}
// Add new user - 'user:1' will be evicted (least recently used)
// because it wasn't "touched" by the skipTouch check
lruCache.set('user:4', 'David');
console.log(lruCache.has('user:1')); // false - evicted
console.log(lruCache.has('user:2')); // true - recently accessed Performance
O(1) average case for get, set, has, and delete operations
Memory efficient with automatic garbage collection
Zero dependencies - no external libraries
TypeScript optimized with proper type inference
Built with ❤️ by Surya Teja
Licensed under MIT