# Como Usar Redis para Cachear Respostas da API de CPF em Node.js

> Aprenda a usar Redis para cachear respostas da API de CPF em Node.js, reduzindo latência, custos e chamadas desnecessárias à API.

**Publicado:** 30/07/2024
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/redis-cachear-respostas-api-cpf-nodejs

---


Para cachear respostas da API de CPF com Redis em Node.js, use a estratégia cache-aside com TTL de 24 horas para resultados positivos e 1 hora para negativos. Essa abordagem reduz a latência de 200–500ms para menos de 5ms, corta até 70% das chamadas à API e mantém resiliência mesmo quando o serviço externo está indisponível.

## Introdução

Consultar a API de CPF para cada requisição pode gerar latência desnecessária e consumir rapidamente os limites do plano contratado. Em muitos cenários, os dados de um CPF não mudam com frequência, o que torna o cache uma estratégia extremamente eficaz. O Redis, por sua velocidade e simplicidade, é a escolha ideal para cachear respostas da API de CPF em aplicações Node.js.

## Por que cachear respostas de CPF

O cache traz benefícios diretos em performance, custo e confiabilidade.

| Benefício | Sem Cache | Com Cache Redis |
|---|---|---|
| Latência média | 200-500ms | 1-5ms |
| Chamadas à API por dia | 10.000 | 2.000-3.000 |
| Custo mensal estimado | R$ 500 | R$ 100-150 |
| Disponibilidade | Depende da API | Alta (cache local) |
| Resiliência a falhas | Baixa | Alta (serve do cache) |

**Redução de latência** -- Redis responde em menos de 5ms, enquanto chamadas à API levam 200ms ou mais.

**Economia de requisições** -- CPFs consultados repetidamente são servidos do cache sem gastar quota.

**Resiliência** -- se a API ficar indisponível, o cache continua servindo dados previamente obtidos.

---

## Configuração do Redis com Node.js

Primeiro, configure a conexão com o Redis usando a biblioteca `ioredis`.

```javascript
import Redis from "ioredis";

const redis = new Redis({
 host: process.env.REDIS_HOST || "127.0.0.1",
 port: parseInt(process.env.REDIS_PORT) || 6379,
 password: process.env.REDIS_PASSWORD || undefined,
 maxRetriesPerRequest: 3,
 retryStrategy(times) {
 const delay = Math.min(times * 200, 2000);
 return delay;
 }
});

redis.on("connect", () => console.log("Redis conectado"));
redis.on("error", (err) => console.error("Erro no Redis:", err));
```

---

## Implementação do cache com TTL

A estratégia de cache-aside (lazy loading) é a mais adequada: consulta o cache primeiro e, se não encontrar, busca na API e armazena no cache. O padrão é descrito nas [diretrizes de segurança da OWASP](https://owasp.org/www-project-web-security-testing-guide/) como uma das abordagens mais seguras para dados sensíveis, pois os dados nunca ficam expostos em trânsito mais do que o necessário.

```javascript
const CACHE_PREFIX = "cpf:";
const CACHE_TTL = 86400; // 24 horas em segundos

async function consultarCPFComCache(cpf) {
 const chaveCache = `${CACHE_PREFIX}${cpf}`;

 // 1. Tentar buscar do cache
 const dadosCache = await redis.get(chaveCache);
 if (dadosCache) {
 console.log(`Cache HIT para CPF ${cpf}`);
 return { fonte: "cache", dados: JSON.parse(dadosCache) };
 }

 console.log(`Cache MISS para CPF ${cpf}`);

 // 2. Buscar da API
 const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
 headers: { "x-api-key": process.env.CPFHUB_API_KEY }
 });
 const resultado = await response.json();

 if (resultado.success) {
 // 3. Armazenar no cache com TTL
 await redis.setex(chaveCache, CACHE_TTL, JSON.stringify(resultado.data));
 return { fonte: "api", dados: resultado.data };
 }

 return { fonte: "api", dados: null, erro: "CPF não encontrado" };
}
```

| Parâmetro | Valor Recomendado | Justificativa |
|---|---|---|
| TTL (dados válidos) | 24 horas (86400s) | Dados de CPF mudam raramente |
| TTL (dados não encontrados) | 1 hora (3600s) | Pode ter sido um erro temporário |
| Prefixo da chave | `cpf:` | Organiza o namespace do Redis |
| Serialização | JSON | Formato padrão e legível |

---

## Cache negativo e invalidação

Cachear respostas negativas (CPF não encontrado) evita consultas repetidas à API para CPFs inválidos, mas com TTL menor.

```javascript
const CACHE_TTL_POSITIVO = 86400; // 24 horas
const CACHE_TTL_NEGATIVO = 3600; // 1 hora
const CACHE_TTL_ERRO = 300; // 5 minutos

async function consultarCPFComCacheCompleto(cpf) {
 const chaveCache = `${CACHE_PREFIX}${cpf}`;

 // Buscar do cache
 const dadosCache = await redis.get(chaveCache);
 if (dadosCache) {
 const parsed = JSON.parse(dadosCache);
 return { fonte: "cache", ...parsed };
 }

 try {
 const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
 headers: { "x-api-key": process.env.CPFHUB_API_KEY }
 });
 const resultado = await response.json();

 if (resultado.success) {
 // Cache positivo: dados encontrados
 await redis.setex(
 chaveCache,
 CACHE_TTL_POSITIVO,
 JSON.stringify({ sucesso: true, dados: resultado.data })
 );
 return { fonte: "api", sucesso: true, dados: resultado.data };
 }

 // Cache negativo: CPF não encontrado
 await redis.setex(
 chaveCache,
 CACHE_TTL_NEGATIVO,
 JSON.stringify({ sucesso: false, motivo: "nao_encontrado" })
 );
 return { fonte: "api", sucesso: false, motivo: "nao_encontrado" };
 } catch (erro) {
 // Cache de erro: falha transitória
 await redis.setex(
 chaveCache,
 CACHE_TTL_ERRO,
 JSON.stringify({ sucesso: false, motivo: "erro_api" })
 );
 return { fonte: "api", sucesso: false, motivo: "erro_api" };
 }
}

// Invalidação manual de um CPF específico
async function invalidarCache(cpf) {
 await redis.del(`${CACHE_PREFIX}${cpf}`);
 console.log(`Cache invalidado para CPF ${cpf}`);
}

// Invalidação de todo o cache de CPF
async function limparCacheCPF() {
 const chaves = await redis.keys(`${CACHE_PREFIX}*`);
 if (chaves.length > 0) {
 await redis.del(...chaves);
 console.log(`${chaves.length} entradas de cache removidas`);
 }
}
```

---

## Monitoramento do cache

Monitorar a eficácia do cache é essencial para ajustar TTLs e identificar problemas.

```javascript
class MonitorCache {
 constructor(redisClient) {
 this.redis = redisClient;
 this.hits = 0;
 this.misses = 0;
 }

 registrarHit() {
 this.hits++;
 }

 registrarMiss() {
 this.misses++;
 }

 get taxaAcerto() {
 const total = this.hits + this.misses;
 return total > 0 ? ((this.hits / total) * 100).toFixed(2) : 0;
 }

 async obterEstatisticas() {
 const info = await this.redis.info("memory");
 const memoriaUsada = info.match(/used_memory_human:(\S+)/)?.[1];
 const totalChaves = await this.redis.dbsize();

 return {
 hits: this.hits,
 misses: this.misses,
 taxaAcerto: `${this.taxaAcerto}%`,
 memoriaUsada,
 totalChaves
 };
 }
}

const monitor = new MonitorCache(redis);

// Exemplo de uso integrado
async function consultarComMonitoramento(cpf) {
 const chaveCache = `${CACHE_PREFIX}${cpf}`;
 const dadosCache = await redis.get(chaveCache);

 if (dadosCache) {
 monitor.registrarHit();
 return JSON.parse(dadosCache);
 }

 monitor.registrarMiss();
 // ... continua com consulta à API
}
```

| Métrica | Meta | Ação se Fora da Meta |
|---|---|---|
| Taxa de acerto | > 70% | Aumentar TTL ou pré-carregar CPFs frequentes |
| Memória usada | < 500MB | Reduzir TTL ou limitar entradas |
| Latência do cache | < 5ms | Verificar conexão Redis e rede |
| Chaves expiradas | Proporcional ao TTL | Ajustar TTL conforme padrão de uso |

---

## Perguntas frequentes

### Por quanto tempo devo manter os dados de CPF no cache?
Para resultados positivos, 24 horas é o padrão recomendado — dados de CPF mudam raramente e esse TTL reduz chamadas à API sem risco relevante de desatualização. Para CPFs não encontrados, use 1 hora, pois pode ser um erro temporário. Para falhas de API, 5 minutos é suficiente.

### Cachear dados de CPF viola a LGPD?
Não, desde que o cache seja um armazenamento interno protegido, com acesso controlado e TTL adequado. O importante é garantir que os dados não sejam acessíveis por sistemas de terceiros e que estejam criptografados em repouso. Documente o cache como operação de tratamento no seu registro de atividades.

### O cache substitui a consulta à API em todos os casos?
Para a maioria dos fluxos de verificação, sim. A exceção são situações onde a atualização dos dados é crítica — por exemplo, revalidação de um cliente suspeito — onde é preferível forçar um cache miss e consultar a API diretamente, usando a função de invalidação manual.

### Qual é a taxa de acerto de cache esperada para uma aplicação típica?
Em aplicações com reuso de CPFs (e-commerce, plataformas com base de clientes recorrentes), taxas de 60–80% são comuns após os primeiros dias. Se a taxa ficar abaixo de 40%, revise se os CPFs consultados são majoritariamente únicos — nesse caso, o cache ainda gera resiliência, mas economiza menos quota.

### Leia também

- [SLA de API de CPF: níveis de disponibilidade e o que exigir do seu provedor](https://cpfhub.io/blog/sla-api-cpf-niveis-disponibilidade)
- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [10 erros mais comuns ao integrar uma API de CPF e como evitá-los](https://cpfhub.io/blog/10-erros-mais-comuns-ao-integrar-uma-api-de-cpf)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)

---

## Conclusão

Cachear respostas da API de CPF com Redis em Node.js é uma otimização fundamental que reduz latência, custos e dependência da disponibilidade da API. A combinação de cache positivo com TTL longo, cache negativo com TTL curto e monitoramento contínuo garante um sistema eficiente e confiável. Ajuste os parâmetros de TTL conforme o padrão de uso da sua aplicação e monitore a taxa de acerto para garantir que o cache esteja cumprindo seu papel.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e integre o cache Redis para reduzir custos e latência nas suas consultas de CPF desde o primeiro deploy.

