Organizando o uso de cache com Redis na sua aplicação

O Redis é uma excelente solução de cache em memória, usado para acelerar respostas e aliviar a carga no banco de dados. Mas com grandes poderes vêm grandes responsabilidades: mal gerenciado, ele pode ser um vilão em vez de herói.
Estrutura básica da aplicação com Redis
Hoje uso um padrão simples e eficaz:
- Admin atualiza os dados (ex: categorias):
- O back-end salva no banco e invalida o cache correspondente no Redis.
- Front-end faz a leitura:
- Primeira tentativa: busca no Redis.
- Se não encontrar, consulta o banco e popula o Redis com o resultado.
Esse padrão é conhecido como cache-aside (lazy loading).
Vantagens dessa abordagem
- Evita dados desatualizados: só lê do Redis se estiver lá, senão pega do banco e atualiza o cache.
- Desacoplamento: o front e o Redis não precisam saber quando os dados mudam. O admin dispara a invalidação.
- Economia de recursos do banco: leitura massiva é desviada pro Redis.
Quando usar cache (ou não)
Saber o que cachear é tão importante quanto saber como.
🔁 Quando usar Redis (boas situações)
- Dados lidos com muita frequência e que mudam com pouca frequência.
Ex: lista de categorias, banners, configurações públicas do app. - Respostas pesadas ou com custo alto de geração.
Ex: joins complexos, agregações, chamadas externas. - Sessões de usuário ou carrinhos temporários.
- Dados de lookup rápido, como status, configs, permissões.
🚫 Evite usar Redis quando:
- O dado muda com muita frequência e precisa estar sempre consistente.
Ex: saldo bancário, estoque em tempo real. - A estrutura muda o tempo todo e a invalidação seria mais cara que o ganho.
- O dado é muito grande (grandes arrays ou documentos) e não tem acesso frequente.
- Você não tem uma estratégia clara de expiração/invalidação.
Cuidados com a memória RAM
Redis armazena tudo em memória. Se não for controlado, pode:
- Estourar o consumo do servidor.
- Forçar o Redis a evitar chaves antigas, gerando falhas silenciosas.
- Competir com sua aplicação ou banco de dados por recursos.
Boas práticas:
- Defina TTL (tempo de expiração) nas chaves.
- Utilize prefixos organizados, como
category:list
,product:123
. - Monitore o uso com
INFO MEMORY
eKEYS
.
Código exemplo (TypeScript + Redis)
// Cache helper
const getCache = async (key: string) => {
const data = await redis.get(key)
return data ? JSON.parse(data) : null
}
const setCache = async (key: string, data: any, ttl = 3600) => {
await redis.set(key, JSON.stringify(data), 'EX', ttl)
}
// Exemplo de leitura no front
export const getCategories = async () => {
const key = RedisKeys.CATEGORY.LIST
const cached = await getCache(key)
if (cached) return cached
const categories = await db.getCategories()
await setCache(key, categories)
return categories
}
Invalidação no admin
export const updateCategory = async (id, payload) => {
await db.updateCategory(id, payload)
await redis.del(RedisKeys.CATEGORY.LIST) // Invalida a lista
}
Organização das chaves do Redis
Para manter o código limpo e evitar duplicações ou erros de digitação, centralize as chaves em um arquivo.
Exemplo: src/cache/redisKeys.ts
export const RedisKeys = {
CATEGORY: {
LIST: 'category:list',
DETAILS: (id: string) => `category:details:${id}`,
},
PRODUCT: {
DETAILS: (id: string) => `product:details:${id}`,
STOCK: (sku: string) => `product:stock:${sku}`,
},
USER: {
SESSION: (id: string) => `user:session:${id}`,
CART: (id: string) => `user:cart:${id}`,
},
}
Usar Redis é poderoso, mas exige disciplina e estratégia. Saber o que cachear, quando invalidar e como gerenciar a memória são decisões cruciais para não transformar performance em problema.
E lembre-se: uma boa organização das chaves é meio caminho andado para um cache confiável e sustentável.