Para processar múltiplas consultas de CPF em paralelo com Node.js, use Promise.allSettled combinado com a biblioteca p-limit para controlar a concorrência. Essa abordagem reduz o tempo de execução de centenas de segundos para poucos segundos, mantendo o respeito aos limites da API e a resiliência do processo.
Introdução
Em cenários como validação de lotes de clientes, migração de bases de dados ou rotinas de compliance, é comum a necessidade de consultar centenas ou milhares de CPFs de uma só vez. Fazer isso sequencialmente pode levar horas, enquanto o processamento paralelo com Node.js reduz drasticamente o tempo de execução.
Consulta sequencial vs. paralela
A diferença de performance entre consultas sequenciais e paralelas é significativa.
| Abordagem | 100 CPFs (200ms/req) | 1.000 CPFs (200ms/req) | 10.000 CPFs (200ms/req) |
|---|---|---|---|
| Sequencial | 20 segundos | 200 segundos | 2.000 segundos |
| Paralela (10 conc.) | 2 segundos | 20 segundos | 200 segundos |
| Paralela (50 conc.) | 0,4 segundos | 4 segundos | 40 segundos |
Sequencial -- cada consulta espera a anterior terminar antes de iniciar; simples, mas lento.
Paralela sem limite -- todas as consultas disparam simultaneamente; rápido, mas sobrecarrega a API e pode causar rate limiting.
Paralela com controle -- um número controlado de consultas roda em paralelo; rápido e respeitoso com os limites da API.
Implementação básica com Promise.allSettled
A abordagem mais simples usa Promise.allSettled para disparar todas as consultas e coletar os resultados.
const fetch = (...args) =>
import("node-fetch").then(({ default: f }) => f(...args));
const API_KEY = process.env.CPFHUB_API_KEY;
const BASE_URL = "https://api.cpfhub.io/cpf";
async function consultarCPF(cpf) {
const response = await fetch(`${BASE_URL}/${cpf}`, {
headers: { "x-api-key": API_KEY }
});
if (!response.ok) {
throw new Error(`HTTP ${response.status} para CPF ${cpf}`);
}
return response.json();
}
async function consultarLoteSimples(cpfs) {
const promessas = cpfs.map((cpf) => consultarCPF(cpf));
const resultados = await Promise.allSettled(promessas);
return resultados.map((resultado, index) => ({
cpf: cpfs[index],
sucesso: resultado.status === "fulfilled",
dados: resultado.status === "fulfilled" ? resultado.value.data : null,
erro: resultado.status === "rejected" ? resultado.reason.message : null
}));
}
// Uso
const cpfs = ["12345678901", "98765432100", "11122233344"];
const resultados = await consultarLoteSimples(cpfs);
console.log(resultados);
Controle de concorrência com p-limit
Para evitar sobrecarregar a API, utilize a biblioteca p-limit para controlar o número de requisições simultâneas.
import pLimit from "p-limit";
const limite = pLimit(10); // Máximo de 10 requisições simultâneas
async function consultarLoteControlado(cpfs) {
const promessas = cpfs.map((cpf) =>
limite(async () => {
try {
const resultado = await consultarCPF(cpf);
return { cpf, sucesso: true, dados: resultado.data };
} catch (erro) {
return { cpf, sucesso: false, erro: erro.message };
}
})
);
return Promise.all(promessas);
}
// Processar 1000 CPFs com no máximo 10 em paralelo
const cpfsGrandes = gerarListaCPFs(1000);
const inicio = Date.now();
const resultados = await consultarLoteControlado(cpfsGrandes);
const duracao = Date.now() - inicio;
const sucessos = resultados.filter((r) => r.sucesso).length;
const falhas = resultados.filter((r) => !r.sucesso).length;
console.log(`Processados: ${resultados.length}`);
console.log(`Sucessos: ${sucessos}, Falhas: ${falhas}`);
console.log(`Duração: ${duracao}ms`);
Implementação manual de pool de concorrência
Para cenários onde não se deseja adicionar dependências, é possível implementar um pool de concorrência manualmente.
async function poolConcorrencia(tarefas, concorrenciaMaxima) {
const resultados = new Array(tarefas.length);
let indiceAtual = 0;
async function worker() {
while (indiceAtual < tarefas.length) {
const indice = indiceAtual++;
try {
resultados[indice] = {
sucesso: true,
dados: await tarefas[indice]()
};
} catch (erro) {
resultados[indice] = { sucesso: false, erro: erro.message };
}
}
}
const workers = Array.from(
{ length: Math.min(concorrenciaMaxima, tarefas.length) },
() => worker()
);
await Promise.all(workers);
return resultados;
}
// Uso
const tarefas = cpfs.map((cpf) => () => consultarCPF(cpf));
const resultados = await poolConcorrencia(tarefas, 15);
| Parâmetro | Valor Recomendado | Justificativa |
|---|---|---|
| Concorrência máxima | 10-20 | Equilibra velocidade e respeito ao rate limit |
| Timeout por requisição | 5.000ms | Evita que uma requisição lenta trave o pool |
| Retentativas | 2-3 | Recupera erros transitórios sem excesso |
| Delay entre retentativas | 1.000ms | Dá tempo para o servidor se recuperar |
Retry com backoff exponencial
Erros transitórios são comuns em operações de lote. Implementar retry com backoff exponencial aumenta a resiliência.
async function consultarComRetry(cpf, tentativas = 3) {
for (let i = 0; i < tentativas; i++) {
try {
const resultado = await consultarCPF(cpf);
return resultado;
} catch (erro) {
if (i === tentativas - 1) throw erro;
const delay = Math.pow(2, i) * 1000 + Math.random() * 500;
console.log(
`Tentativa ${i + 1} falhou para CPF ${cpf}. ` +
`Retentando em ${Math.round(delay)}ms...`
);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
async function consultarLoteResilient(cpfs, concorrencia = 10) {
const limite = pLimit(concorrencia);
const promessas = cpfs.map((cpf) =>
limite(async () => {
try {
const resultado = await consultarComRetry(cpf);
return { cpf, sucesso: true, dados: resultado.data };
} catch (erro) {
return { cpf, sucesso: false, erro: erro.message };
}
})
);
return Promise.all(promessas);
}
Perguntas frequentes
O que é necessário para implementar validação de CPF neste contexto?
A validação de CPF exige uma chamada à API com o número do documento e a chave de autenticação. A CPFHub.io retorna o status do CPF, nome do titular e data de nascimento em menos de 200ms, permitindo a verificação em tempo real durante o cadastro ou transação.
A API CPFHub.io funciona para todos os volumes de consulta?
Sim. O plano gratuito oferece 50 consultas por mês sem cartão de crédito — ideal para testes e projetos pequenos. Para volumes maiores, o plano Pro inclui 1.000 consultas mensais por R$149. Se o limite for ultrapassado, a API não bloqueia: cobra R$0,15 por consulta adicional.
Como garantir conformidade com a LGPD ao usar uma API de CPF?
Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário (não guarde o CPF cru se um token bastar), implemente controle de acesso aos logs de consulta e documente a base legal para o tratamento. A ANPD orienta que dados de identificação devem ser tratados com o princípio da necessidade.
Quanto tempo leva para integrar a API CPFHub.io?
A integração básica leva menos de 30 minutos: crie uma conta em cpfhub.io, gere a API key no painel e faça uma chamada GET para https://api.cpfhub.io/cpf/{CPF} com o header x-api-key. A documentação inclui exemplos em Python, Node.js, PHP, Java e outras linguagens.
Conclusão
O processamento paralelo de consultas de CPF em Node.js é uma técnica essencial para lidar com operações em lote de forma eficiente. A combinação de controle de concorrência, retry com backoff exponencial e tratamento robusto de erros garante que o processo seja rápido, resiliente e respeitoso com os limites da API. Escolha a concorrência adequada ao seu plano e monitore as métricas de sucesso para ajustar os parâmetros ao longo do tempo.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a processar lotes de CPF em paralelo com alta performance hoje mesmo.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



