Encontre a requisição cara antes de alterar o banco de dados
Comece a partir de uma ação do usuário: carregamento de categoria, busca de artigo, adicionar ao carrinho ou submissão de pedido. Capture sua rota, contagem de queries, duração no banco, linhas retornadas e duração da requisição. Uma página lenta também pode aguardar código da aplicação ou outra dependência, então não diagnostique apenas pelo tempo de carregamento da página.
Um plano de query é a rota do banco através de tabelas, índices, junções, ordenações e agregações. No PostgreSQL, EXPLAIN mostra essa rota. EXPLAIN ANALYZE executa a instrução e reporta linhas e tempos reais, portanto use uma query representativa segura. Uma grande diferença entre linhas estimadas e reais é motivo para investigar estatísticas ou condições, não um pedido automático de índice.
Vincule uma query candidata a uma rota e resultado, para que um relatório só no dashboard não supere um checkout lento.
Registre tempos antes da mudança e tráfego comparável sem registrar identificadores de cliente, tokens ou valores relacionados a cartão.
Projete índices para o caminho de acesso que você realmente usa
Um índice é uma estrutura mantida que pode ajudar a localizar linhas ou retorná-las em ordem; não é um interruptor universal de velocidade. Comece pelos filtros, chaves de junção e ordem (ORDER BY) de uma query importante, e então confirme o índice proposto em um plano. A documentação do PostgreSQL mostra que um índice B-tree correspondente pode satisfazer ORDER BY sem uma ordenação separada, especialmente com um LIMIT pequeno.
Índices adicionam armazenamento e trabalho de escrita porque inserts, updates e deletes os mantêm. Para uma query que precisa de uma grande fração de uma tabela, um varredura sequencial (sequential scan) e ordenação explícita podem ser mais rápidos. Teste em dados semelhantes à produção e mantenha um índice apenas quando o benefício justificar o custo.
Use os filtros reais da query e o ORDER BY, incluindo um critério de desempate determinístico quando a interface precisar de ordem estável.
Verifique se um índice é usado e o que ele custa durante escritas; reavalie conforme dados e tráfego mudam.
Torne a paginação estável e acessível
A paginação por número de página normalmente usa LIMIT mais OFFSET. Sempre imponha uma ordem previsível. O PostgreSQL alerta que sem ORDER BY, LIMIT pode retornar um subconjunto imprevisível; valores diferentes de LIMIT ou OFFSET podem gerar subconjuntos inconsistentes porque o otimizador pode escolher planos diferentes.
Offsets grandes merecem atenção porque linhas puladas ainda precisam ser computadas. Para navegação profunda em catálogo, histórico de pedidos ou arquivo, considere paginação por cursor ou por keyset (keyset pagination): solicite linhas após o último valor de ordenação estável visto e desempate único. Defina como registros novos ou deletados aparecem antes de mudar a interface.
Retorne a menor página útil em vez de um resultado sem limite.
Decida se a interface realmente precisa de um total exato a cada requisição.
Cacheie leituras sem servir respostas erradas
O cache reutiliza um resultado anterior em vez de reconstruí-lo a partir do banco. Comece na camada HTTP para páginas públicas e repetíveis e ativos versionados, porque um acerto de cache pode evitar trabalho de aplicação e banco de dados. web.dev recomenda cache de longa duração para URLs versionadas; mudar a URL é o mecanismo prático de invalidação.
A política de cache é uma decisão de correção. Um cache compartilhado pode reutilizar uma resposta entre usuários, então não compartilhe saída específica de conta, carrinho, preço ou autorização, a menos que isso seja projetado e testado para esse escopo. Cache-Control private restringe a reutilização ao cache do navegador, enquanto no-store orienta caches a não reterem a resposta.
Separe saída pública de catálogo ou artigo de saída específica de sessão, localização e sensível a permissões.
Defina quem pode ver um valor stale, por quanto tempo e o caminho de invalidação ou revalidação.
Proteja a capacidade de conexões em vez de apenas aumentar o teto
Uma conexão é uma sessão cliente ativa com o banco de dados. Workers, jobs agendados, previews ou tentativas repetidas podem esgotar slots mesmo quando queries individuais parecem aceitáveis. O max_connections do PostgreSQL controla conexões concorrentes, é definido na inicialização do servidor, e um valor maior aloca mais recursos incluindo memória compartilhada. Aumentá-lo sem um modelo de workload pode apenas mover a falha.
Estabeleça um orçamento único entre workers web, jobs em background, administração e réplicas. Use pool com limite onde couber, preserve folga para recuperação e aplique timeouts para que trabalho abandonado não espere indefinidamente. Números seguros dependem do mecanismo, memória, mix de queries e limites do provedor; confirme-os com o operador.
Inclua processos web, filas, tarefas agendadas, migrações, ferramentas de relatórios e jobs de deploy.
Corte a concorrência e use backoff para que uma falha não multiplique a demanda por conexões.
Observe o custo das queries com contexto e controles de privacidade
Classifique o trabalho do banco por impacto total, não por uma amostra lenta isolada. Uma query moderadamente lenta chamada milhares de vezes pode importar mais que um relatório raro. O pg_stat_statements do PostgreSQL agrega dados de planejamento e execução incluindo chamadas, tempo total e médio de execução, linhas e atividade de buffer. Ele requer configuração do servidor e um restart para adicionar ou remover; o rastreamento de planejamento pode adicionar overhead.
Conecte grupos de queries à rota, versão de release e janela de tempo. O OpenTelemetry aconselha coletar o texto da query por padrão apenas após sanitização que substitui literais, e usar um sumário de baixa cardinalidade para agrupamento. Isso ajuda responsáveis a ver tendências sem exportar dados de clientes ou criar um rótulo para cada valor.
Revise duração, tempo total, chamadas, erros, conexões e linhas; cada um expõe um modo de falha diferente.
Use consultas parametrizadas e verifique se literais são removidos antes que traces ou logs saiam da aplicação.
Envie mudanças de banco de dados como trabalho reversível de confiabilidade
Trate um índice, reescrita, política de cache, ajuste de pool ou mudança de esquema como uma mudança em produção com um responsável, medida de sucesso e decisão de rollback. Valide em um ambiente representativo, libere para uma fatia limitada e observe a jornada afetada. Mais rápido não é sucesso se a mudança retornar dados errados, faltantes, duplicados ou stale.
Mudanças de esquema exigem cuidado porque versões de aplicação podem se sobrepor. A orientação do Google Cloud descreve uma sequência compatível: libere uma aplicação que lide com o esquema antigo e o novo, altere o esquema e então libere a funcionalidade que o usa. Isso preserva uma rota de rollback da aplicação. Locking e comportamento de mudança online diferem por engine e serviço gerenciado; obtenha revisão qualificada para sistemas de alto volume ou relacionados a pagamento.
Nomeie a rota, sinais de performance e correção, e o limiar que interrompe o rollout.
Verifique performance e correção em uma fatia controlada antes de alargar; pratique o caminho de retorno fora de um incidente.
