Como fazer throttling progressivo em consultas de CPF para evitar bloqueios

Aprenda a implementar throttling progressivo em consultas de CPF via API para respeitar rate limits e evitar bloqueios.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como fazer throttling progressivo em consultas de CPF para evitar bloqueios

Throttling progressivo em consultas de CPF é uma técnica de controle proativo de consumo que ajusta automaticamente a cadência de requisições para manter os custos previsíveis. Na CPFHub.io, a API nunca bloqueia — ao superar o limite do plano, cada consulta adicional é cobrada a R$0,15 — portanto, o objetivo do throttling é responsabilidade financeira, não evitar erros de bloqueio.

Introdução

Quando sua aplicação processa grandes volumes de CPFs, a falta de controle sobre o ritmo de requisições pode resultar em custos inesperados no fim do mês. O throttling progressivo resolve isso ajustando dinamicamente a taxa de consultas com base no consumo observado — mais rápido quando há margem, mais lento quando o orçamento está próximo do limite. A ferramenta get_quota_info do servidor MCP da CPFHub.io e o painel em app.cpfhub.io/settings/billing são os meios recomendados para monitorar o consumo em tempo real.


Throttling fixo vs. progressivo

  • Throttling fixo -- Intervalo constante entre requisições (ex: sempre 2 segundos). Simples, mas não se adapta à situação.

  • Throttling progressivo -- Começa rápido e desacelera ao detectar que o orçamento ou a cota estão próximos do limite. Retorna à velocidade normal quando há margem disponível.


Implementação básica: token bucket

O algoritmo token bucket controla a taxa de requisições permitindo um "balde" que se enche de tokens a uma taxa fixa:

import time
import threading

class TokenBucket:
    def __init__(self, taxa_por_segundo, capacidade_maxima):
        self.taxa = taxa_por_segundo
        self.capacidade = capacidade_maxima
        self.tokens = capacidade_maxima
        self.ultimo_reabastecimento = time.monotonic()
        self.lock = threading.Lock()

    def consumir(self, tokens=1):
        with self.lock:
            agora = time.monotonic()
            decorrido = agora - self.ultimo_reabastecimento
            self.tokens = min(
                self.capacidade,
                self.tokens + decorrido * self.taxa
            )
            self.ultimo_reabastecimento = agora

            if self.tokens >= tokens:
                self.tokens -= tokens
                return True
            return False

    def aguardar_token(self, tokens=1):
        while not self.consumir(tokens):
            time.sleep(0.05)

# Plano Pro: 1 req/seg
bucket = TokenBucket(taxa_por_segundo=1.0, capacidade_maxima=1)

Throttling progressivo com controle de consumo

A implementação completa monitora o consumo acumulado e desacelera conforme a cota mensal se aproxima:

import requests
import time
import threading

class ThrottleProgressivo:
    def __init__(self, api_key, taxa_base=0.5, limite_mensal=50):
        self.api_key = api_key
        self.taxa_base = taxa_base  # requisicoes por segundo
        self.taxa_atual = taxa_base
        self.intervalo_minimo = 1.0 / taxa_base
        self.intervalo_atual = self.intervalo_minimo
        self.multiplicador_cautela = 2.0
        self.fator_recuperacao = 0.9
        self.intervalo_maximo = 30.0
        self.consultas_realizadas = 0
        self.limite_mensal = limite_mensal
        self.consecutivos_ok = 0
        self.lock = threading.Lock()
        self.session = requests.Session()
        self.session.headers.update({
            'x-api-key': api_key,
            'Accept': 'application/json'
        })

    def consultar(self, cpf):
        with self.lock:
            intervalo = self.intervalo_atual

        time.sleep(intervalo)

        try:
            response = self.session.get(
                f'https://api.cpfhub.io/cpf/{cpf}',
                timeout=15
            )

            self._ajustar_taxa(response.status_code)

            if response.status_code == 200:
                with self.lock:
                    self.consultas_realizadas += 1
                return response.json()
            else:
                return {'error': f'http_{response.status_code}'}

        except requests.exceptions.Timeout:
            self._aumentar_intervalo()
            return {'error': 'timeout'}

    def _ajustar_taxa(self, status_code):
        with self.lock:
            percentual_consumido = self.consultas_realizadas / self.limite_mensal

            if percentual_consumido > 0.8:
                # Acima de 80% da cota: dobrar intervalo para conter custos extras
                self.intervalo_atual = min(
                    self.intervalo_atual * self.multiplicador_cautela,
                    self.intervalo_maximo
                )
                print(f'Consumo: {percentual_consumido:.0%}. Intervalo: {self.intervalo_atual:.2f}s')

            elif status_code == 200:
                self.consecutivos_ok += 1
                # Recuperacao gradual apos 5 respostas OK consecutivas
                if self.consecutivos_ok >= 5:
                    self.intervalo_atual = max(
                        self.intervalo_atual * self.fator_recuperacao,
                        self.intervalo_minimo
                    )
                    self.consecutivos_ok = 0

    def _aumentar_intervalo(self):
        with self.lock:
            self.intervalo_atual = min(
                self.intervalo_atual * 1.5,
                self.intervalo_maximo
            )

    @property
    def status(self):
        return {
            'intervalo_atual': round(self.intervalo_atual, 2),
            'taxa_efetiva': round(1.0 / self.intervalo_atual, 2),
            'consultas_realizadas': self.consultas_realizadas,
            'consecutivos_ok': self.consecutivos_ok
        }

Uso prático para processamento em lote

throttle = ThrottleProgressivo('SUA_CHAVE_DE_API', taxa_base=0.5, limite_mensal=50)

cpfs = ['12345678900', '98765432100', '11122233344']
resultados = []

for cpf in cpfs:
    resultado = throttle.consultar(cpf)
    resultados.append({'cpf': cpf, 'resultado': resultado})
    print(f'CPF: {cpf} | Status: {throttle.status}')

print(f'\nProcessados: {len(resultados)}')

Implementação em Node.js

class ThrottleProgressivo {
    constructor(apiKey, taxaBase = 0.5, limiteMensal = 50) {
        this.apiKey = apiKey;
        this.intervaloAtual = 1000 / taxaBase; // em ms
        this.intervaloMinimo = 1000 / taxaBase;
        this.intervaloMaximo = 30000;
        this.multiplicadorCautela = 2.0;
        this.fatorRecuperacao = 0.9;
        this.consecutivosOk = 0;
        this.consultasRealizadas = 0;
        this.limiteMensal = limiteMensal;
    }

    async consultar(cpf) {
        await this._aguardar(this.intervaloAtual);

        try {
            const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
                method: 'GET',
                headers: {
                    'x-api-key': this.apiKey,
                    'Accept': 'application/json'
                },
                signal: AbortSignal.timeout(15000)
            });

            this._ajustarTaxa(response.status);

            if (response.ok) {
                this.consultasRealizadas++;
                return await response.json();
            }
            return { error: `http_${response.status}` };

        } catch (error) {
            this.intervaloAtual = Math.min(
                this.intervaloAtual * 1.5,
                this.intervaloMaximo
            );
            return { error: error.message };
        }
    }

    _ajustarTaxa(status) {
        const percentualConsumido = this.consultasRealizadas / this.limiteMensal;

        if (percentualConsumido > 0.8) {
            // Acima de 80% da cota: desacelerar para conter custos extras
            this.intervaloAtual = Math.min(
                this.intervaloAtual * this.multiplicadorCautela,
                this.intervaloMaximo
            );
        } else if (status === 200) {
            this.consecutivosOk++;
            if (this.consecutivosOk >= 5) {
                this.intervaloAtual = Math.max(
                    this.intervaloAtual * this.fatorRecuperacao,
                    this.intervaloMinimo
                );
                this.consecutivosOk = 0;
            }
        }
    }

    _aguardar(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

// Uso
const throttle = new ThrottleProgressivo(process.env.CPFHUB_API_KEY, 0.5, 50);
const resultado = await throttle.consultar('12345678900');

Estrategias complementares

Retry com jitter

Adicionar aleatoriedade ao intervalo evita que múltiplas instâncias sincronizem seus retries:

import random

def intervalo_com_jitter(intervalo_base):
    jitter = random.uniform(0, intervalo_base * 0.3)
    return intervalo_base + jitter

Circuit breaker de custo

Se o consumo acumulado ultrapassar o limite planejado, suspenda o lote até revisão manual:

if self.consultas_realizadas >= self.limite_mensal:
    print('Cota mensal atingida. Pausando processamento para revisão de custos.')
    print('Verifique o consumo em app.cpfhub.io/settings/billing')
    raise SystemExit('Limite de consultas atingido')

Monitorando o consumo

Registre métricas para entender o comportamento do throttle e planejar upgrades de plano:

  • Intervalo médio -- Quanto tempo, em média, entre cada chamada.

  • Percentual de cota consumido -- Acompanhe via get_quota_info (MCP) ou no painel app.cpfhub.io/settings/billing.

  • Custo projetado -- Consultas acima da cota custam R$0,15 cada; monitore antes de atingir o limite.

  • Throughput efetivo -- Quantas consultas por minuto estão sendo processadas.

A OWASP recomenda o monitoramento contínuo de consumo de APIs externas como parte das boas práticas de segurança e governança de custos.


Perguntas frequentes

A API da CPFHub.io bloqueia requisições quando a cota é ultrapassada?

Não. A CPFHub.io nunca retorna HTTP 429 nem bloqueia a aplicação. Ao superar o limite do plano, cada consulta adicional é cobrada a R$0,15. O throttling progressivo existe para controlar proativamente esse custo, não para evitar bloqueios.

Como monitorar o consumo de cota em tempo real?

Use a ferramenta get_quota_info do servidor MCP da CPFHub.io para consultar o consumo atual programaticamente, ou acesse app.cpfhub.io/settings/billing para visualizar o histórico e o saldo do mês.

Qual a diferença entre throttling fixo e progressivo no contexto da CPFHub.io?

O throttling fixo aplica um intervalo constante entre requisições, independentemente do consumo. O throttling progressivo monitora a cota consumida e desacelera automaticamente quando o percentual se aproxima do limite — reduzindo o risco de cobranças inesperadas sem sacrificar o throughput quando há margem disponível.

Quando faz sentido fazer upgrade para o plano Pro?

Quando o volume mensal de consultas ultrapassa 50 com frequência, o plano Pro (R$149/mês, 1.000 consultas + R$0,15/extra) se torna mais econômico. O throttling progressivo ajuda a quantificar esse volume antes de decidir pelo upgrade.


Conclusão

Throttling progressivo é a abordagem inteligente para controlar o custo de processamento em lote com a CPFHub.io. Ao ajustar automaticamente a cadência de requisições com base no consumo acumulado, sua aplicação processa o máximo possível dentro do orçamento planejado — sem surpresas no faturamento e sem interrupções no fluxo.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece 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.

Redação CPFHub.io

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.

WhatsAppFale conosco via WhatsApp