Introdução: Por que o cache é criticamente importante para aplicações TypeScript
Aplicações web modernas em TypeScript enfrentam cargas crescentes e exigências de velocidade de resposta. O cache não é apenas uma opção, mas uma necessidade para qualquer aplicação de nível de produção. Sem ele, cada requisição ao banco de dados ou API externa se torna uma operação custosa, aumentando o tempo de resposta em 10 a 100 vezes.
Neste artigo, vamos analisar três abordagens principais para cache em TypeScript: Redis — cache distribuído, Memcached — alternativa leve e soluções embutidas (in-memory cache). Você aprenderá como escolher a ferramenta adequada e implementá-la com exemplos de código.
1. Cache embutido: In-Memory Cache em TypeScript
A maneira mais simples e rápida é armazenar dados diretamente na memória RAM do processo. Para TypeScript/Node.js, isso é ideal para aplicações monolíticas ou microsserviços com uma única instância.
Implementação de um cache in-memory simples
Vamos criar uma classe SimpleCache com suporte a TTL (tempo de vida):
interface CacheEntry<T> {
value: T;
expiresAt: number;
}
class SimpleCache<T> {
private store = new Map<string, CacheEntry<T>>();
private defaultTTL: number; // em milissegundos
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();
}
}
// Exemplo de uso
const userCache = new SimpleCache<User>(30000); // TTL 30 segundos
userCache.set('user:123', { id: 123, name: 'Ana' });
const cachedUser = userCache.get('user:123');
Prós e contras do cache in-memory
- Prós: velocidade máxima (nanossegundos), sem latência de rede, simplicidade de implementação.
- Contras: dados são perdidos ao reiniciar a aplicação, limitados pela RAM de um único processo, não funcionam com escalonamento horizontal.
Quando usar: para armazenar em cache resultados de cálculos pesados, configurações, dados estáticos que raramente mudam.
2. Redis: Cache distribuído para TypeScript
Redis é o data store in-memory mais popular, usado como cache, message broker e banco de dados. Para TypeScript, utilizamos a biblioteca ioredis.
Instalação e configuração básica
npm install ioredis
npm install @types/ioredis -D
Vamos criar um serviço para trabalhar com 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
```