Pular para o conteúdo principal

Desempenho da API: limitação de taxa, paginação e processamento assíncrono

Crie APIs de alto desempenho com algoritmos de limitação de taxa, paginação baseada em cursor, filas de tarefas assíncronas e práticas recomendadas de compactação de resposta.

E
ECOSIRE Research and Development Team
|15 de março de 202613 min de leitura2.4k Palavras|

Sua API é tão rápida quanto seu endpoint mais lento sob carga de pico. Um único endpoint não otimizado que mantém conexões de banco de dados por 5 segundos pode esgotar seu pool de conexões e causar falhas em cascata em toda a plataforma.

Parte da nossa série Desempenho e escalabilidade

Leia o guia completo

Sua API é tão rápida quanto seu endpoint mais lento sob carga de pico. Um único endpoint não otimizado que mantém conexões de banco de dados por 5 segundos pode esgotar seu pool de conexões e causar falhas em cascata em toda a plataforma. A engenharia de desempenho da API se concentra em três pilares: proteger sua API contra sobrecarga (limitação de taxa), lidar com grandes conjuntos de dados com eficiência (paginação) e retirar operações caras do ciclo de solicitação (processamento assíncrono).

Principais conclusões

  • Token bucket e janela deslizante são os dois algoritmos de limitação de taxa que cobrem 95% dos casos de uso – escolha com base se você deseja tolerância a rajadas ou aplicação estrita
  • A paginação baseada em cursor supera a paginação offset para grandes conjuntos de dados porque evita a contagem de linhas ignoradas
  • O processamento assíncrono com filas de trabalhos reduz os tempos de resposta P95 ao mover o envio de e-mail, a geração de PDF e a entrega de webhook para fora do caminho da solicitação
  • A compactação de resposta com Brotli reduz o tamanho da carga útil em 70-85%, traduzindo-se diretamente em uma renderização mais rápida do lado do cliente

Algoritmos de limitação de taxa

A limitação de taxa protege sua API contra abusos, garante a alocação justa de recursos e evita falhas em cascata durante picos de tráfego. O algoritmo escolhido determina como as rajadas são tratadas e quão previsível é o comportamento limitante para os consumidores.

AlgoritmoTratamento de explosãoUso de memóriaPrecisãoMelhor para
Janela fixaPermite burst 2x no limite da janelaMuito baixoBaixoCasos de uso simples, APIs internas
Registro de janela deslizanteSem rajadas, precisoAlto (armazena carimbos de data/hora)Muito altoAPIs financeiras, conformidade rigorosa
Balcão de janela deslizanteExplosão mínima de limiteBaixoAltoAPIs públicas de uso geral
Balde de tokensPermite rajadas controladasBaixoModeradoAPIs com padrões de explosão naturais
Balde com vazamentoSuaviza todo o tráfegoBaixoAltoAPIs que exigem rendimento constante

Balde de tokens

O algoritmo token bucket é a escolha mais prática para a maioria das APIs. Um balde contém tokens até uma capacidade máxima. Os tokens são adicionados a uma taxa fixa (a taxa de recarga). Cada solicitação consome um token. Se o bucket estiver vazio, a solicitação será rejeitada ou colocada na fila.

A principal vantagem do token bucket é a tolerância ao burst. Se um cliente não fizer solicitações por um tempo, seu bucket estará cheio e ele poderá fazer uma explosão de solicitações até a capacidade do bucket. Isso corresponde aos padrões naturais de uso: um cliente que carrega um painel pode fazer 20 solicitações em rápida sucessão e depois nada por 30 segundos.

Exemplo de configuração para uma API de comércio eletrônico:

  • Tamanho do balde: 100 tokens
  • Taxa de recarga: 10 tokens por segundo
  • Isso permite rajadas de até 100 solicitações, mantendo 10 solicitações por segundo a longo prazo

Contador de janela deslizante

O contador de janelas deslizantes combina a precisão do registro da janela deslizante com a eficiência de memória da janela fixa. Ele mantém contadores para a janela atual e anterior e, em seguida, calcula uma contagem ponderada com base em quão longe na janela atual a solicitação cai.

Para uma janela de 60 segundos avaliada em 45 segundos, a contagem efetiva é: (contagem de janelas anteriores * 0,25) + (contagem de janelas atuais). Isso elimina o problema de estouro de limites de janelas fixas sem armazenar registros de data e hora de solicitação individuais.

Implementação com Redis

Redis é o armazenamento de apoio padrão para limitação de taxa distribuída porque fornece operações de incremento atômico com TTL. Use INCR com EXPIRE para janelas fixas ou conjuntos classificados com ZADD e ZRANGEBYSCORE para janelas deslizantes. Para token bucket, os scripts Redis Lua fornecem operações atômicas de verificação e decremento.

Cabeçalhos de limitação de taxa comunicam limites aos consumidores da API:

  • X-RateLimit-Limit -- máximo de solicitações permitidas na janela
  • X-RateLimit-Remaining -- solicitações restantes na janela atual
  • X-RateLimit-Reset -- Carimbo de data e hora Unix quando a janela é reiniciada
  • Retry-After -- segundos até o cliente tentar novamente (em 429 respostas)

Estratégias de paginação

Cada ponto final da lista deve ser paginado. O retorno de conjuntos de resultados ilimitados desperdiça largura de banda, sobrecarrega o banco de dados e corre o risco de erros de tempo limite à medida que os dados aumentam.

Paginação de deslocamento

A paginação de deslocamento usa cláusulas SQL LIMIT e OFFSET. O cliente solicita ?page=3&limit=20 e o servidor traduz para OFFSET 40 LIMIT 20.

Vantagens:

  • Simples de implementar e entender
  • Os clientes podem ir diretamente para qualquer página
  • A contagem total permite a interface do usuário "Página X de Y"

Desvantagens:

  • O desempenho diminui com deslocamentos altos - OFFSET 1000000 ainda verifica 1.000.000 de linhas antes de retornar resultados
  • Resultados inconsistentes quando os dados mudam entre páginas (as linhas mudam à medida que novos dados são inseridos ou excluídos)
  • A consulta de contagem total (COUNT(*)) pode ser cara em tabelas grandes

Paginação baseada em cursor

A paginação baseada em cursor usa um cursor opaco (normalmente uma chave primária codificada ou carimbo de data/hora) para marcar a posição no conjunto de resultados. O cliente solicita ?cursor=abc123&limit=20 e o servidor usa o cursor como uma cláusula WHERE: WHERE id > decoded(abc123) LIMIT 20.

Vantagens:

  • Desempenho consistente, independentemente da posição no conjunto de dados – sem digitalização de deslocamento
  • Resultados estáveis mesmo quando os dados mudam entre páginas
  • Ajuste natural para rolagem infinita e feeds em tempo real

Desvantagens:

  • Não é possível pular para páginas arbitrárias (não "Ir para a página 50")
  • Mais complexo de implementar, especialmente com ordens de classificação de múltiplas colunas
  • A contagem total deve ser fornecida separadamente, se necessário

Qual paginação usar

CenárioRecomendaçãoRazão
Tabelas de dados administrativos com números de páginaDeslocamentoOs usuários esperam navegação na página
Rolagem infinita móvelCursorDesempenho em qualquer profundidade
API consumida por integraçõesCursorPaginação estável para processamento em lote
Conjuntos de dados pequenos (menos de 10.000 linhas)OuA diferença de desempenho é insignificante
Grandes conjuntos de dados (mais de 100.000 linhas)CursorO deslocamento torna-se inutilmente lento
Feeds em tempo real (bate-papo, notificações)CursorConsistência à medida que novos dados chegam

Formato de resposta de paginação

Uma resposta de paginação bem projetada inclui metadados que os clientes precisam para navegar:

{
  "data": [],
  "pagination": {
    "total": 15432,
    "limit": 20,
    "hasMore": true,
    "nextCursor": "eyJpZCI6MTAwfQ=="
  }
}

Processamento assíncrono com filas de trabalhos

Os endpoints síncronos da API devem retornar respostas dentro de 200 ms. Qualquer operação que demore mais – envio de e-mails, geração de PDFs, processamento de imagens, chamada de APIs externas, execução de relatórios – deve ser movida para uma fila de trabalhos em segundo plano.

O padrão da fila de trabalhos

  1. O endpoint da API valida a solicitação e cria um registro de trabalho
  2. O trabalho é colocado em uma fila (Redis, RabbitMQ, SQS)
  3. A API retorna imediatamente com uma resposta 202 aceita e um ID de trabalho
  4. Um processo de trabalho seleciona o trabalho e o executa de forma assíncrona
  5. O cliente pesquisa o status do trabalho ou recebe um retorno de chamada do webhook após a conclusão

Casos de uso assíncronos comuns

Envio de e-mail – As operações SMTP levam de 500ms a 3s, dependendo do provedor. O enfileiramento de e-mails reduz o tempo de resposta da API e permite a lógica de repetição para falhas transitórias sem bloquear o usuário.

Geração de PDF – A geração de faturas, relatórios ou arquivos de exportação consome muita CPU e muita memória. Executá-los em trabalhadores dedicados evita a contenção de recursos com o tratamento de solicitações de API.

Entrega de webhook – webhooks de saída dependem da disponibilidade de servidores de terceiros. Enfileira entregas de webhook com nova tentativa de espera exponencial (1s, 2s, 4s, 8s, até 5 minutos) para lidar com falhas temporárias sem bloquear seu sistema.

Importação e exportação de dados – O processamento de uploads de CSV com 100.000 linhas nunca deve acontecer em um ciclo de solicitação. Aceite o upload, retorne um ID de trabalho e processe as linhas em lotes.

Seleção de fila

Tecnologia de filaMelhor paraConsiderações
BullMQ (apoiado por Redis)Aplicativos Node.js, integração NestJSÓtima experiência do desenvolvedor, painel integrado
CoelhoMQSistemas multilíngues, roteamento complexoMaduro, suporta padrões de reconhecimento de mensagens
AWSSQSInfraestrutura gerenciada e sem servidorSem gerenciamento de servidor, pagamento por mensagem
KafkaStreaming de eventos, alto rendimentoExagero para filas de trabalho simples, excelente para fornecimento de eventos

Otimização de resposta

Além da lógica do aplicativo, a própria resposta pode ser otimizada em termos de tamanho e velocidade de entrega.

Compressão

Habilite a compactação de resposta para reduzir o tamanho da carga útil na rede. Algoritmos de compactação modernos reduzem significativamente as cargas baseadas em texto (JSON, HTML, CSS, JavaScript).

AlgoritmoTaxa de compressãoCusto da CPUSuporte ao navegador
gzipRedução de 60-75%BaixoUniversais
BrotliRedução de 70-85%ModeradoTodos os navegadores modernos
zstdRedução de 70-85%BaixoEmergentes (ainda não universais)

Use Brotli para ativos estáticos (pré-compactados em tempo de construção) e gzip como substituto para respostas dinâmicas. No NestJS, o middleware de compactação lida com isso automaticamente, mas na produção, deixe o Nginx lidar com a compactação para descarregar a CPU do seu servidor de aplicativos.

Seleção de Campo

Permita que os consumidores da API solicitem apenas os campos de que precisam. GraphQL faz isso inerentemente, mas APIs REST podem oferecer suporte à seleção de campos com um parâmetro de consulta ?fields=id,name,price. Isso reduz o tamanho da carga útil e pode otimizar consultas ao banco de dados selecionando apenas as colunas necessárias.

Cabeçalhos de cache de resposta

Defina cabeçalhos Cache-Control apropriados nas respostas da API. Os endpoints de lista pública (produtos, categorias) podem usar Cache-Control: public, max-age=300 para armazenar em cache por 5 minutos. Os endpoints autenticados devem usar Cache-Control: private, no-cache para evitar o cache do CDN e, ao mesmo tempo, permitir o cache do navegador com revalidação.

Para obter mais informações sobre estratégias de cache, consulte nosso guia detalhado sobre caching Redis, CDN e HTTP.


Gerenciamento de conexão

Conexões de banco de dados e HTTP são recursos finitos que devem ser gerenciados cuidadosamente sob carga.

Pool de conexões de banco de dados

Um pool de conexões mantém um conjunto de conexões de banco de dados reutilizáveis. Sem pooling, cada solicitação de API abre uma nova conexão de banco de dados (sobrecarga de 50 a 100 ms) e a fecha após a resposta. Com o pooling, as solicitações emprestam conexões do pool e as devolvem quando terminam.

Fórmula de dimensionamento do pool: conexões = (core_count * 2) + efetivo_spindle_count. Para um servidor de 4 núcleos com armazenamento SSD, 10 a 20 conexões por instância de aplicativo é um bom ponto de partida. Monitore a utilização do pool: se exceder regularmente 80%, aumente o tamanho do pool ou otimize a duração da consulta.

HTTP Keep-Alive

Habilite o keep-alive HTTP para conexões com serviços upstream (bancos de dados, Redis, APIs externas). Isso reutiliza conexões TCP em vez de estabelecer novas por solicitação, eliminando o handshake TCP e a sobrecarga de negociação TLS (50-200 ms por nova conexão).


Perguntas frequentes

Quais limites de taxa devo definir para uma API pública?

Comece com limites conservadores e ajuste com base em padrões de uso legítimos. Um ponto de partida comum são 100 solicitações por minuto para usuários autenticados e 20 solicitações por minuto para usuários anônimos. Monitore as taxas de resposta 429 – se usuários legítimos atingirem limites com frequência, aumente-os. Forneça limites mais altos para níveis de API premium.

Como lidar com a paginação quando os dados mudam entre páginas?

A paginação baseada em cursor lida com isso naturalmente porque ancora em uma posição específica nos dados classificados. Com a paginação offset, o documento resultante pode mudar entre as páginas. Para casos de uso críticos (relatórios financeiros, exportações de dados), faça um snapshot dos dados no início da paginação e paginação sobre o snapshot.

Devo usar REST ou GraphQL para desempenho?

REST com seleção de campos e cache adequado é mais rápido para endpoints simples e bem definidos. GraphQL elimina busca excessiva e insuficiente para requisitos de dados complexos, mas adiciona sobrecarga de análise de consulta e torna o cache HTTP mais difícil. Use REST para APIs públicas com necessidades de cache e GraphQL para APIs internas que atendem a requisitos complexos de dados de front-end.

Como monitoro o desempenho da API em produção?

Acompanhe os tempos de resposta P50, P95 e P99 por endpoint. Defina alertas no P95 violando seu SLO (normalmente de 200 a 500 ms). Use o rastreamento distribuído para dividir o tempo gasto em banco de dados, cache, serviços externos e lógica de aplicativo. Consulte nosso guia sobre monitoramento e observabilidade para configuração detalhada.


O que vem a seguir

Comece auditando seus endpoints de API em busca de paginação ausente, endpoints públicos desprotegidos sem limitação de taxa e operações síncronas que deveriam ser assíncronas. Essas três alterações normalmente reduzem os tempos de resposta do P95 em 50-70% e evitam os incidentes de produção mais comuns.

Para obter a perspectiva completa da engenharia de desempenho, consulte nosso guia de pilares sobre escalonamento de sua plataforma de negócios. Para a camada de banco de dados que alimenta sua API, leia nosso guia de otimização de consulta.

ECOSIRE cria APIs de alto desempenho para plataformas de negócios em Odoo ERP e arquiteturas personalizadas. Entre em contato conosco para uma avaliação de desempenho da API.


Publicado por ECOSIRE — ajudando empresas a escalar com soluções baseadas em IA em Odoo ERP, Shopify eCommerce e OpenClaw AI.

E

Escrito por

ECOSIRE Team

Redação técnica

A equipe de redação técnica da ECOSIRE escreve sobre Odoo ERP, e-commerce com Shopify, agentes de IA, análise de dados com Power BI, automação com GoHighLevel e boas práticas de software empresarial. Nossos guias ajudam as empresas a tomar decisões de tecnologia bem fundamentadas.

ECOSIRE

Expanda o seu negócio com ECOSIRE

Soluções empresariais em ERP, comércio eletrônico, IA, análise e automação.

Mais de Desempenho e escalabilidade

Depuração e monitoramento de webhook: o guia completo para solução de problemas

Domine a depuração de webhook com este guia completo que cobre padrões de falha, ferramentas de depuração, estratégias de repetição, painéis de monitoramento e práticas recomendadas de segurança.

Teste de carga k6: teste de resistência de suas APIs antes do lançamento

Domine o teste de carga k6 para APIs Node.js. Abrange aumentos de usuários virtuais, limites, cenários, HTTP/2, testes WebSocket, painéis Grafana e padrões de integração de CI.

Configuração de produção Nginx: SSL, cache e segurança

Guia de configuração de produção Nginx: terminação SSL, HTTP/2, cabeçalhos de cache, cabeçalhos de segurança, limitação de taxa, configuração de proxy reverso e padrões de integração Cloudflare.

Ajuste de desempenho Odoo: PostgreSQL e otimização de servidor

Guia especializado para ajuste de desempenho do Odoo 19. Abrange configuração do PostgreSQL, indexação, otimização de consultas, cache Nginx e dimensionamento de servidores para implantações corporativas.

Teste e monitoramento de agentes de IA em produção

Um guia completo para testar e monitorar agentes de IA em ambientes de produção. Abrange estruturas de avaliação, observabilidade, detecção de desvios e resposta a incidentes para implantações OpenClaw.

Agentes de monitoramento de conformidade com OpenClaw

Implante agentes OpenClaw AI para monitoramento contínuo de conformidade. Automatize verificações regulatórias, aplicação de políticas, geração de trilhas de auditoria e relatórios de conformidade.