# Como Otimizar Requisições de API em Ruby para Melhorar a Performance

> Aprenda técnicas para otimizar requisições à API de CPF em Ruby, incluindo connection pooling, cache, compressão e processamento paralelo.

**Publicado:** 11/08/2024
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/otimizar-requisicoes-api-ruby-performance

---


A performance das requisições HTTP em Ruby pode variar significativamente dependendo de como o cliente HTTP é configurado e utilizado. Em aplicações que consultam APIs de CPF com frequência, otimizações como connection pooling, cache, compressão e processamento paralelo podem reduzir a latência em até 80% e o consumo de recursos em proporções similares.

## Introdução

Cada requisição mal configurada à API de CPF pode adicionar centenas de milissegundos desnecessários ao tempo de resposta da aplicação. Combinando as técnicas certas — pooling de conexões, cache em memória e execução paralela — é possível transformar um fluxo lento em algo rápido e escalável.

## Connection pooling com persistent HTTP

Criar uma nova conexão TCP para cada requisição adiciona latência desnecessária. O connection pooling reutiliza conexões existentes.

```ruby
require "faraday"
require "faraday-net_http_persistent"

# Cliente com connection pooling (reutiliza conexões TCP)
module CpfHub
 class Client
 POOL_SIZE = 10

 def initialize
 @connection = Faraday.new(url: "https://api.cpfhub.io") do |conn|
 conn.headers["x-api-key"] = ENV["CPFHUB_API_KEY"]
 conn.headers["Accept-Encoding"] = "gzip"
 conn.options.timeout = 10
 conn.options.open_timeout = 5
 conn.adapter :net_http_persistent, pool_size: POOL_SIZE do |http|
 http.idle_timeout = 30
 end
 end
 end

 def consultar(cpf)
 resposta = @connection.get("/cpf/#{cpf}")
 JSON.parse(resposta.body)
 rescue Faraday::Error => e
 { "success" => false, "error" => e.message }
 end
 end
end

# Singleton para reutilizar em toda a aplicação
cliente = CpfHub::Client.new
resultado = cliente.consultar("12345678901")
```

| Métrica | Sem Pool | Com Pool |
|---|---|---|
| Latência primeira requisição | 250ms | 250ms |
| Latência requisições seguintes | 200ms | 50ms |
| Conexões TCP abertas | 1 por requisição | Pool compartilhado |
| Overhead de handshake TLS | Toda requisição | Apenas na primeira |
| Consumo de memória | Alto | Moderado |

---

## Cache em memória com LRU

Para CPFs consultados repetidamente, um cache em memória evita requisições desnecessárias.

```ruby
require "lru_redux"

module CpfHub
 class CachedClient
 DEFAULT_TTL = 3600 # 1 hora em segundos

 def initialize(max_size: 1000, ttl: DEFAULT_TTL)
 @client = Client.new
 @cache = LruRedux::TTL::ThreadSafeCache.new(max_size, ttl)
 @hits = 0
 @misses = 0
 end

 def consultar(cpf)
 cpf_limpo = cpf.gsub(/\D/, "")

 cached = @cache[cpf_limpo]
 if cached
 @hits += 1
 return cached.merge("fonte" => "cache")
 end

 @misses += 1
 resultado = @client.consultar(cpf_limpo)

 if resultado["success"]
 @cache[cpf_limpo] = resultado
 end

 resultado.merge("fonte" => "api")
 end

 def estatisticas
 total = @hits + @misses
 taxa = total.positive? ? (@hits.to_f / total * 100).round(2) : 0

 {
 hits: @hits,
 misses: @misses,
 taxa_acerto: "#{taxa}%",
 entradas_cache: @cache.count
 }
 end

 def invalidar(cpf)
 @cache.delete(cpf.gsub(/\D/, ""))
 end

 def limpar
 @cache.clear
 end
 end
end
```

---

## Processamento paralelo com threads

Ruby suporta threads para I/O concorrente, ideal para múltiplas consultas de CPF simultâneas.

```ruby
require "concurrent-ruby"

module CpfHub
 class ParallelClient
 def initialize(concorrencia: 5)
 @client = CachedClient.new
 @pool = Concurrent::FixedThreadPool.new(concorrencia)
 end

 def consultar_lote(cpfs)
 futures = cpfs.map do |cpf|
 Concurrent::Future.execute(executor: @pool) do
 @client.consultar(cpf)
 end
 end

 futures.map.with_index do |future, index|
 resultado = future.value(10) # Timeout de 10 segundos
 {
 cpf: cpfs[index],
 sucesso: resultado&.dig("success") || false,
 dados: resultado&.dig("data"),
 erro: future.rejected? ? future.reason.message : nil
 }
 end
 end

 def estatisticas
 @client.estatisticas
 end

 def shutdown
 @pool.shutdown
 @pool.wait_for_termination(30)
 end
 end
end

# Uso
cliente_paralelo = CpfHub::ParallelClient.new(concorrencia: 10)
cpfs = %w[12345678901 98765432100 11122233344 44455566677]
resultados = cliente_paralelo.consultar_lote(cpfs)

resultados.each do |r|
 puts "#{r[:cpf]}: #{r[:sucesso] ? r[:dados]['name'] : r[:erro]}"
end

cliente_paralelo.shutdown
```

| Parâmetro | Valor Recomendado | Justificativa |
|---|---|---|
| Threads no pool | 5-10 | Equilibra concorrência e uso de recursos |
| Timeout por thread | 10 segundos | Evita threads travadas indefinidamente |
| Cache max_size | 1.000-10.000 | Depende do volume de CPFs únicos |
| Cache TTL | 1-24 horas | Dados de CPF mudam raramente |

---

## Middleware de logging e métricas

Adicionar logging estruturado às requisições ajuda a identificar gargalos e otimizar.

```ruby
module CpfHub
 class LoggingMiddleware < Faraday::Middleware
 def call(env)
 inicio = Process.clock_gettime(Process::CLOCK_MONOTONIC)

 resposta = @app.call(env)

 duracao = (
 (Process.clock_gettime(Process::CLOCK_MONOTONIC) - inicio) * 1000
 ).round(2)

 log_dados = {
 metodo: env.method.upcase,
 url: env.url.to_s.gsub(/\d{11}/, "***CPF***"),
 status: resposta.status,
 duracao_ms: duracao,
 timestamp: Time.now.iso8601
 }

 if duracao > 1000
 Rails.logger.warn("[CpfHub] Requisicao lenta: #{log_dados}")
 else
 Rails.logger.info("[CpfHub] #{log_dados}")
 end

 resposta
 end
 end
end

# Registrar o middleware no Faraday
Faraday::Middleware.register_middleware(
 cpfhub_logging: CpfHub::LoggingMiddleware
)
```

---

## Benchmark comparativo

Comparação das diferentes estratégias de otimização em um lote de 100 CPFs.

```ruby
require "benchmark"

cpfs = gerar_lista_cpfs(100)

Benchmark.bm(25) do |x|
 x.report("Sequencial sem cache") do
 cliente_simples = CpfHub::Client.new
 cpfs.each { |cpf| cliente_simples.consultar(cpf) }
 end

 x.report("Sequencial com cache") do
 cliente_cache = CpfHub::CachedClient.new
 cpfs.each { |cpf| cliente_cache.consultar(cpf) }
 end

 x.report("Paralelo sem cache") do
 cliente_paralelo = CpfHub::ParallelClient.new(concorrencia: 10)
 cliente_paralelo.consultar_lote(cpfs)
 cliente_paralelo.shutdown
 end

 x.report("Paralelo com cache") do
 cliente_completo = CpfHub::ParallelClient.new(concorrencia: 10)
 # Segunda execução (com cache)
 cliente_completo.consultar_lote(cpfs)
 cliente_completo.shutdown
 end
end
```

| Estratégia | 100 CPFs | 1.000 CPFs |
|---|---|---|
| Sequencial sem cache | ~20s | ~200s |
| Sequencial com cache (2a exec.) | ~0.1s | ~1s |
| Paralelo sem cache (10 threads) | ~2s | ~20s |
| Paralelo com cache (2a exec.) | ~0.01s | ~0.1s |

---

## 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](https://www.gov.br/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.

### Leia também

- [Diferença entre validação de CPF e consulta de CPF: quando usar cada uma](https://cpfhub.io/blog/diferenca-entre-validacao-de-cpf-e-consulta-de-cpf-quando-usar-cada-uma)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [Onboarding digital em fintechs: como validar CPF em menos de 30 segundos](https://cpfhub.io/blog/onboarding-digital-em-fintechs-como-validar-cpf-em-menos-de-30-segundos)
- [KYC no Brasil: quais setores são obrigados a validar CPF por lei](https://cpfhub.io/blog/kyc-no-brasil-quais-setores-sao-obrigados-a-validar-cpf-por-lei)

---

## Conclusão

Otimizar requisições à API de CPF em Ruby envolve múltiplas camadas: connection pooling para reduzir overhead de rede, cache para evitar consultas repetidas, processamento paralelo para acelerar lotes e logging para identificar gargalos. A combinação dessas técnicas pode reduzir o tempo de processamento de minutos para milissegundos em cenários com dados repetidos.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a otimizar suas integrações Ruby com connection pooling e cache desde a primeira requisição.

