Uma API pode responder em 80 milissegundos e ainda assim atender poucas pessoas. Outra pode processar milhares de requisições por segundo, mas fazer parte dos usuários esperar vários segundos.
Esses exemplos mostram duas dimensões diferentes de desempenho:
- Latência: quanto tempo uma operação leva;
- Throughput: quantas operações o sistema conclui em um intervalo.
As duas métricas aparecem em praticamente toda discussão de System Design. Elas ajudam a transformar frases vagas, como “o sistema precisa ser rápido”, em requisitos que podem ser medidos, testados e comparados.
O que é latência?
Latência é o tempo decorrido entre o início de uma operação e seu término. Em uma requisição HTTP, costuma ser o intervalo entre o cliente enviar a requisição e receber a resposta completa.
Ela pode ser expressa em nanossegundos, microssegundos, milissegundos ou segundos, conforme o tipo de sistema. Para uma aplicação web, milissegundos geralmente são a unidade mais útil.
Cliente envia a requisição ──────────────── Cliente recebe a resposta
latência total
A latência percebida pelo usuário é formada por vários trechos:
Rede de ida
+ espera em fila
+ processamento da aplicação
+ consultas e dependências
+ rede de volta
= latência observada
Por isso, dizer que “a API levou 300 ms” não identifica sozinho a causa. O tempo pode estar no transporte pela rede, em uma fila, no código, no banco de dados ou em outro serviço.
Latência não é apenas tempo de processamento
O tempo de serviço é quanto uma operação leva enquanto está efetivamente sendo processada. O tempo de resposta inclui também a espera antes desse processamento.
Imagine um worker que leva 40 ms para executar uma tarefa, mas recebe trabalho mais rápido do que consegue processar. Uma tarefa pode esperar 900 ms na fila e consumir apenas 40 ms de CPU:
Espera na fila: 900 ms
Processamento: 40 ms
Tempo total: 940 ms
O código da tarefa não ficou mais lento. O sistema ficou congestionado.
O que é throughput?
Throughput, ou vazão, é a quantidade de trabalho concluído em determinado intervalo. A unidade deve indicar claramente qual trabalho está sendo contado:
- Requisições por segundo, ou RPS;
- Transações por segundo, ou TPS;
- Mensagens processadas por segundo;
- Arquivos por minuto;
- Registros gravados por segundo;
- Bytes transferidos por segundo.
throughput = operações concluídas / intervalo de tempo
Se uma API conclui 12.000 requisições em 60 segundos, seu throughput médio nesse período é:
12.000 / 60 = 200 requisições por segundo
Contar operações concluídas é importante. Aceitar 500 mensagens por segundo e processar apenas 300 significa que o restante está acumulando em uma fila; não que o sistema sustenta 500 mensagens por segundo indefinidamente.
Throughput não é largura de banda
Os termos são próximos, mas não são equivalentes. Largura de banda é a capacidade teórica ou nominal de um canal. Throughput é o volume útil efetivamente entregue.
Uma conexão de 1 Gbit/s não garante 1 Gbit/s de dados úteis para a aplicação. Protocolos, contenção, perdas, tamanho das mensagens e limites dos componentes reduzem a vazão observada.
Como latência e throughput se relacionam?
Latência e throughput não são opostos. Melhorar uma não garante melhorar a outra.
Um sistema pode reduzir a latência de uma operação sem aumentar a quantidade total que processa. Também pode usar lotes para aumentar o throughput, mas fazer cada item esperar mais tempo até o lote ser formado.
O comportamento mais importante aparece quando a carga se aproxima da capacidade:
Carga baixa → pouca espera → latência estável
Carga crescente → mais uso → throughput aumenta
Perto do limite → filas crescem → latência sobe rapidamente
Acima do limite → acúmulo e erros; throughput deixa de acompanhar a demanda
Enquanto existe capacidade livre, o sistema costuma absorver mais requisições com pouca mudança na latência. Quando um recurso satura — CPU, conexões, disco, rede ou uma dependência — novas operações passam a esperar. A fila aumenta a latência mesmo que o tempo de processamento de cada operação permaneça igual.
Por que a média não é suficiente?
Uma média resume os valores, mas pode esconder a experiência de uma parte relevante dos usuários.
Considere dez requisições:
9 requisições × 100 ms = 900 ms
1 requisição × 5.000 ms = 5.000 ms
Média = 590 ms
Nenhum usuário recebeu uma resposta em 590 ms. Nove receberam em 100 ms e um esperou 5 segundos.
Por isso, latência costuma ser apresentada com percentis:
- p50: 50% das operações terminaram nesse tempo ou menos;
- p95: 95% terminaram nesse tempo ou menos;
- p99: 99% terminaram nesse tempo ou menos.
Se a latência p95 é 400 ms, até 95% das operações observadas terminaram em no máximo 400 ms. Os 5% restantes foram mais lentos.
| Métrica | O que mostra | Uso comum |
|---|---|---|
| p50 | Experiência típica | Acompanhar o comportamento central |
| p95 | Cauda relevante para muitos usuários | Definir metas de APIs e jornadas |
| p99 | Casos lentos raros, mas recorrentes em escala | Investigar filas, pausas e dependências |
| Máximo | Pior valor observado | Diagnóstico, com cuidado para valores isolados |
Quanto maior o tráfego, mais pessoas encontram a cauda da distribuição. Em um serviço com milhões de requisições, 1% ainda representa muitos casos. A escolha do percentil deve refletir o impacto no produto, não uma regra universal.
Meça no contexto certo
Uma métrica sem contexto pode levar a conclusões erradas. Ao registrar latência e throughput, associe pelo menos:
- Operação ou endpoint;
- Período observado;
- Volume e padrão da carga;
- Taxa de erros;
- Tamanho das requisições e respostas;
- Região e tipo de cliente, quando relevantes;
- Estado dos recursos e dependências.
Misturar operações diferentes também distorce o resultado. Um endpoint de health check e uma geração de relatório não deveriam formar uma única distribuição de latência.
Também devemos medir em mais de um ponto. A métrica do servidor não inclui necessariamente DNS, conexão, rede e renderização no cliente. Para entender a experiência real, é útil comparar a visão do cliente com os tempos internos de cada etapa.
Concorrência conecta as duas métricas
Para um sistema estável, uma aproximação conhecida como Lei de Little relaciona três medidas:
concorrência ≈ throughput × latência média
Se um serviço conclui 200 requisições por segundo e cada uma permanece no sistema por 0,25 segundo, existem em média cerca de 50 requisições em andamento:
200 req/s × 0,25 s = 50 requisições concorrentes
Essa relação ajuda a estimar conexões, workers e memória. Ela exige unidades compatíveis e um período estável, sem uma fila crescendo indefinidamente. Também não substitui um teste de carga: é um modelo para raciocinar sobre capacidade.
Quando utilizar essas métricas?
Latência e throughput são úteis desde a definição dos requisitos até a operação em produção.
Use-as para:
- Definir objetivos mensuráveis de desempenho;
- Planejar capacidade para tráfego normal e picos;
- Comparar alternativas de arquitetura;
- Configurar testes de carga;
- Detectar saturação e regressões;
- Escolher sinais para autoscaling;
- Avaliar se uma otimização trouxe resultado real.
Um requisito como “a busca deve ser rápida” é difícil de validar. Uma formulação melhor seria:
Com 300 requisições por segundo,
95% das buscas devem responder em até 250 ms,
com menos de 1% de erros.
Agora estão definidos a carga, o percentil, o limite de latência e a taxa de erros. Ainda seria necessário descrever o ambiente e o tamanho dos dados, mas o requisito já pode orientar um teste.
Exemplo prático: uma API de checkout
Imagine uma API de checkout com a seguinte meta:
Carga normal: 100 req/s
Pico esperado: 400 req/s
Meta de latência: p95 ≤ 500 ms
Taxa de erros: < 0,5%
Um teste aumenta a carga gradualmente e produz estes resultados:
| Carga enviada | Throughput concluído | Latência p95 | Erros |
|---|---|---|---|
| 100 req/s | 100 req/s | 180 ms | 0% |
| 250 req/s | 250 req/s | 310 ms | 0,1% |
| 400 req/s | 388 req/s | 1.400 ms | 1,8% |
| 500 req/s | 392 req/s | 4.800 ms | 7,2% |
Entre 400 e 500 requisições enviadas por segundo, o throughput concluído quase não cresce. A latência e os erros, porém, aumentam bastante. O sistema está próximo de sua capacidade útil.
As métricas internas mostram que o pool de conexões com o banco está cheio. Requisições aguardam uma conexão antes de executar a consulta.
Uma decisão possível
A equipe encontra duas consultas redundantes, reduz o tempo de transação e configura um limite de concorrência para não sobrecarregar o banco. Depois, repete o mesmo teste no mesmo ambiente.
O objetivo não é afirmar que todo gargalo se resolve com otimização de consultas. É mostrar o processo:
Definir a meta
→ aumentar a carga de forma controlada
→ observar latência, throughput e erros
→ localizar o recurso saturado
→ mudar uma hipótese
→ repetir o teste
Medir somente a latência poderia mostrar que o sistema ficou lento, mas não onde sua capacidade parou de crescer. Medir somente throughput poderia esconder uma fila cada vez maior e uma experiência ruim para o usuário.
Estratégias para reduzir latência
A estratégia correta depende de onde o tempo é gasto. Algumas opções comuns são:
- Aproximar conteúdo do usuário com CDN;
- Evitar chamadas de rede desnecessárias;
- Usar cache para leituras frequentes e adequadas;
- Criar índices para padrões reais de consulta;
- Paralelizar operações independentes;
- Retirar do caminho síncrono trabalhos que podem ser assíncronos;
- Reduzir filas com limites de concorrência e capacidade suficiente;
- Definir timeouts e orçamentos de latência entre dependências.
Cada opção traz custos. Cache exige uma política de atualização; paralelismo consome mais recursos; processamento assíncrono muda a experiência e o modelo de consistência.
Estratégias para aumentar throughput
Para aumentar a quantidade sustentável de trabalho concluído, podemos:
- Remover o gargalo identificado;
- Processar itens em lotes quando a espera for aceitável;
- Usar concorrência com limites seguros;
- Distribuir trabalho entre mais instâncias;
- Particionar dados ou filas;
- Reduzir contenção em locks e recursos compartilhados;
- Aplicar backpressure para impedir crescimento ilimitado das filas.
Mais paralelismo nem sempre aumenta throughput. Se todos os workers disputam o mesmo banco, lock ou limite externo, adicionar concorrência pode aumentar contenção e reduzir a vazão.
Vantagens
- Tornam requisitos de desempenho verificáveis;
- Ajudam a localizar o ponto de saturação;
- Permitem comparar mudanças antes e depois;
- Orientam capacidade, autoscaling e limites de concorrência;
- Revelam diferenças entre a experiência típica e a cauda lenta.
Limitações e trade-offs
| Decisão | Benefício | Custo ou risco |
|---|---|---|
| Processar em lote | Maior eficiência e throughput | Cada item pode esperar a formação do lote |
| Aumentar concorrência | Mais trabalho simultâneo | Contenção, filas em dependências e maior uso de recursos |
| Usar cache | Menor latência e menos carga na origem | Invalidação e possível dado desatualizado |
| Recusar excesso de carga | Protege a capacidade e a latência das requisições aceitas | Parte das chamadas recebe erro ou precisa tentar novamente |
| Otimizar para p99 | Melhora a experiência da cauda | Pode exigir custo alto para poucos casos |
Erros comuns
Usar apenas a média
A média esconde a distribuição e pode suavizar casos muito lentos. Acompanhe percentis adequados ao produto e também o volume de amostras.
Informar latência sem carga
“A API responde em 100 ms” não diz se o teste ocorreu com uma ou mil requisições por segundo. Registre a latência junto da carga, do ambiente e da taxa de erros.
Confundir tráfego enviado com throughput concluído
Requisições aceitas podem estar esperando, falhando ou acumulando em filas. Meça o trabalho realmente concluído e o tamanho ou a idade do backlog.
Ignorar erros ao testar capacidade
Um serviço que responde rapidamente com erro não atingiu o objetivo. Latência, throughput e taxa de sucesso devem ser avaliados em conjunto.
Aumentar concorrência sem observar dependências
Mais threads, conexões ou instâncias podem apenas deslocar o gargalo. Verifique limites do banco, de serviços externos e da infraestrutura compartilhada.
Testar apenas por poucos segundos
Testes curtos podem não revelar aquecimento, filas, vazamentos, compactação, throttling ou limites que aparecem com carga sustentada. O tempo do teste deve representar o comportamento que queremos validar.
Gerar uma carga irreal
Se a ferramenta de teste espera cada resposta antes de enviar a próxima requisição, ela pode reduzir a pressão justamente quando o sistema fica lento. O modelo de chegada, a concorrência e a distribuição das operações devem se aproximar do uso esperado.
Perguntas de entrevista
- Qual é a diferença entre latência e throughput?
- Por que uma latência média baixa não garante uma boa experiência para todos os usuários?
- O que significam p50, p95 e p99?
- Como filas afetam a latência quando o throughput chega ao limite?
- Um aumento de concorrência sempre aumenta throughput? Por quê?
- Que métricas você observaria durante um teste de carga além da latência?
- Como batching pode melhorar throughput e piorar latência?
- Como a Lei de Little ajuda a estimar a concorrência de um sistema?
- O que caracteriza o ponto de saturação de um serviço?
- Como você escreveria um requisito mensurável de desempenho para uma API?
Próximos conteúdos
Depois de aprender a medir demanda e desempenho, estude escalabilidade vertical e horizontal para entender como aumentar a capacidade do componente que limita o sistema.
Em seguida, observe essas métricas em um desenho completo, como o estudo de caso de um encurtador de URLs. Ele permite discutir caminhos de leitura e escrita, cache, banco de dados e estimativas de capacidade.
Guarde este modelo mental:
Latência → quanto tempo cada operação leva
Throughput → quanto trabalho termina por intervalo
Saturação → quando mais demanda vira espera e erro
Percentis → como a experiência se distribui
Desempenho não é um único número. É o comportamento do sistema sob uma carga conhecida, observado pela experiência de quem usa e pelos limites de quem processa.