Introduction: Why is caching needed in TypeScript?
Modern web applications require high response speed and minimal database load. Caching is one of the most effective ways to achieve this. In the TypeScript (and Node.js) ecosystem, developers have three main approaches available: distributed systems (Redis, Memcached) and built-in solutions (in-memory cache). In this article, we will analyze each of them, provide practical examples in TypeScript, and help you choose the optimal option for your project.
Caching allows you to store frequently requested data in a fast storage, avoiding repeated expensive operations (database queries, computations, external API calls). A proper caching strategy can reduce server response time by 10-100 times.
1. Built-in Caching in TypeScript (In-Memory)
The simplest way is to store data directly in the Node.js process memory. This does not require external services, which is ideal for small applications or prototypes.
1.1. Using Map and WeakMap
Built-in JavaScript collections are an excellent foundation for a simple cache. Example implementation with TTL (Time To Live):
type CacheEntry<T> = { value: T; expiresAt: number;};
class SimpleCache<T> { private store = new Map<string, CacheEntry<T>>();
set(key: string, value: T, ttlMs: number = 60000): void { this.store.set(key, { value, expiresAt: Date.now() + ttlMs, }); }
get(key: string): T | undefined { const entry = this.store.get(key); if (!entry) return undefined; if (Date.now() > entry.expiresAt) { this.store.delete(key); return undefined; } return entry.value; }
delete(key: string): boolean { return this.store.delete(key); }
clear(): void { this.store.clear(); }}
// Usageconst userCache = new SimpleCache<object>();userCache.set('user:1', { name: 'Alexey' }, 30000); // TTL 30 secconsole.log(userCache.get('user:1'));1.2. The node-cache Library
For production solutions, it is better to use the proven node-cache library. It provides advanced features: automatic cleanup, statistics, and events.
import NodeCache from 'node-cache';
const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });
// Save an objectconst success = myCache.set('myKey', { data: 'value' });if (success) console.log('Cache saved');
// Readconst value = myCache.get('myKey');console.log(value); // { data: 'value' }
// Get statisticsconst stats = myCache.getStats();console.log(`Hits: ${stats.hits}, Misses: ${stats.misses}`);Pros: simplicity, zero network latency, no need to install services.
Cons: cache is lost when the application restarts, not suitable for distributed systems.
2. Caching with Redis in TypeScript
Redis is the most popular caching solution in production. It runs as a separate server, supports complex data structures, and is resilient to application restarts.
2.1. Connecting ioredis
The ioredis library is the de facto standard for working with Redis from TypeScript. It supports clustering, Pub/Sub, and Pipeline.
import Redis from 'ioredis';
const redis = new Redis({ host: 'localhost', port: 6379, retryStrategy: (times) => Math.min(times * 50, 2000),});
// Check connectionredis.on('connect', () => console.log('Connected to Redis'));redis.on('error', (err) => console.error('Redis error:', err));2.2. Example of caching with TTL
async function getCachedData(key: string): Promise<string | null> { const cached = await redis.get(key); if (cached) { console.log('Data from