Performance está cheia de regras populares ("cache resolve
tudo", "ORM é lento", "GC é o problema") que mais atrapalham
do que ajudam. Cada decisão abaixo é confronto direto com uma
dessas regras — e a resposta saudável quase sempre começa
com "depende da medição".
Vale otimizar antes de medir?
Quase nunca. A frase de Donald Knuth — "premature
optimization is the root of all evil" — é mal citada,
mas o argumento original (de 1974) sobrevive: a
intuição humana é notoriamente ruim para identificar
onde o tempo de um programa está sendo gasto. Profilers
existem por isso. As exceções são duas e estreitas: (1)
decisões arquiteturais que são caras de reverter
depois (escolha de modelo de execução, layout de dados
crítico, protocolo de rede), e (2) padrões reconhecidos
como armadilhas estruturais (N+1 query, alocação em
loop quente, retry storm). Fora dessas, a regra é
medir, encontrar o gargalo, mexer, medir de novo.
Latência média ou percentis?
Percentis. Em sistemas reais, distribuições de latência
são fortemente assimétricas — a média é dominada pela
cauda, e duas distribuições com a mesma média podem ter
experiências de usuário radicalmente diferentes. P50
(mediana) conta como a maioria das requests se comporta;
P95 e P99 contam o que o usuário experiencia em momentos
ruins; P99.9 conta o que sustentadores noturnos vêem.
Em sistemas distribuídos com fan-out alto (uma request
atinge dezenas de serviços), o P99 individual de cada
serviço vira a latência mediana do usuário — fenômeno
documentado por Dean & Barroso em 2013. Métrica
de equipe sênior é histograma, não média.
Cache em qual camada?
Em todas, idealmente, mas com responsabilidades
distintas. Browser cache (via Cache-Control)
elimina viagem de rede para conteúdo estável. CDN
elimina viagem ao origin para conteúdo público dinâmico
(com cuidado de Vary em endpoints
personalizados). Cache distribuído (Redis) na camada de
aplicação serve dado mutável compartilhado entre
réplicas. Cache local in-memory cobre lookup tables
quase imutáveis. Cada camada tem invalidação distinta,
e a soma — quando bem orquestrada — entrega latência
ordens de magnitude melhor que qualquer camada
isolada. Quando mal orquestrada, vira fonte de bugs
de "às vezes vejo dado antigo" que ninguém consegue
reproduzir.
Profiling em produção ou em ambiente de teste?
Em produção. Hoje, com continuous profiling
(Pyroscope, Datadog Continuous Profiler, Parca), o
overhead é < 2% e os dados refletem o tráfego real —
tipos de query, distribuições de payload, padrões de
uso. Profiling em ambiente de teste mente: load
sintético raramente reproduz o caso real, e otimizações
baseadas nele frequentemente atacam o gargalo errado. A
regra de senior é continuous profiling sempre
ligado em produção, com retenção curta (poucos
dias) e alertas em mudança brusca de hot path.
Otimizar para latência ou para throughput?
São métricas distintas, frequentemente em tensão. APIs
voltadas a humano (web, mobile, voz) priorizam latência
— o usuário sente cada milissegundo da P99. Sistemas
voltados a processamento batch (ETL, treinamento, geração
de relatório) priorizam throughput — quanto custa por
registro processado, quantos por hora. A confusão clássica
é otimizar throughput de um sistema interativo, fazendo
batches grandes que matam a P99. Ou o oposto: otimizar
latência de um pipeline batch, processando registros um a
um quando o ganho seria batch. Articular qual é a métrica
relevante antes de otimizar evita esforço perdido.