Introducción: Por qué el almacenamiento en caché es crítico para aplicaciones TypeScript
Las aplicaciones web modernas en TypeScript enfrentan cargas crecientes y requisitos de velocidad de respuesta. El almacenamiento en caché no es solo una opción, sino una necesidad para cualquier aplicación de nivel de producción. Sin él, cada solicitud a la base de datos o API externa se convierte en una operación costosa, aumentando el tiempo de respuesta entre 10 y 100 veces.
En este artículo, analizaremos tres enfoques principales para el almacenamiento en caché en TypeScript: Redis — caché distribuido, Memcached — alternativa ligera y soluciones integradas (in-memory cache). Aprenderá cómo elegir la herramienta adecuada e implementarla con ejemplos de código.
1. Caché integrado: In-Memory Cache en TypeScript
La forma más simple y rápida es almacenar datos directamente en la memoria RAM del proceso. Para TypeScript/Node.js, esto es ideal para aplicaciones monolíticas o microservicios con una sola instancia.
Implementación de un caché in-memory simple
Crearemos una clase SimpleCache con soporte para TTL (tiempo de vida):
interface CacheEntry<T> { value: T; expiresAt: number;}
class SimpleCache<T> { private store = new Map<string, CacheEntry<T>>(); private defaultTTL: number; // en milisegundos
constructor(defaultTTL: number = 60000) { this.defaultTTL = defaultTTL; }
set(key: string, value: T, ttl?: number): void { const expiresAt = Date.now() + (ttl ?? this.defaultTTL); this.store.set(key, { value, expiresAt }); }
get(key: string): T | null { const entry = this.store.get(key); if (!entry) return null; if (Date.now() > entry.expiresAt) { this.store.delete(key); return null; } return entry.value; }
has(key: string): boolean { return this.get(key) !== null; }
delete(key: string): void { this.store.delete(key); }
clear(): void { this.store.clear(); }}
// Ejemplo de usoconst userCache = new SimpleCache<User>(30000); // TTL 30 segundosuserCache.set('user:123', { id: 123, name: 'Ana' });const cachedUser = userCache.get('user:123');Ventajas y desventajas del caché in-memory
- Ventajas: velocidad máxima (nanosegundos), sin latencia de red, simplicidad de implementación.
- Desventajas: los datos se pierden al reiniciar la aplicación, limitados por la RAM de un solo proceso, no funcionan con escalado horizontal.
Cuándo usarlo: para almacenar en caché resultados de cálculos pesados, configuraciones, datos estáticos que raramente cambian.
2. Redis: Caché distribuido para TypeScript
Redis es el almacén de datos in-memory más popular, utilizado como caché, broker de mensajes y base de datos. Para TypeScript usamos la librería ioredis.
Instalación y configuración básica
npm install ioredisnpm install @types/ioredis -DCrearemos un servicio para trabajar con Redis:
import Redis from 'ioredis';
class RedisCacheService { private client: Redis; private defaultTTL: number;
constructor(ttlSeconds: number = 3600) { this.client = new Redis({ host: process.env.REDIS_HOST || 'localhost', port: Number(process.env.REDIS_PORT) || 6379, retryStrategy: (times) => Math.min(times * 50, 2000), }); this.defaultTTL = ttlSeconds; }
async set<T>(key: string, value: T, ttl?: number): Promise<void> { const serialized = JSON.stringify(value); const ttlToUse = ttl ?? this.defaultTTL; await this.client.setex(key, ttlToUse, serialized); }
async get<T>(key: string): Promise<T | null> { const data = await this.client.get(key); if (!data) return null; try { return