Duração da Solicitação do TTFB: Reduza o Tempo de Processamento do Servidor

A duração da solicitação é o tempo que seu servidor gasta processando uma solicitação. É o maior contribuinte para o TTFB na maioria dos sites. Aprenda sobre Server-Timing, cache, otimização de banco de dados e correções de plataforma.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-03

Reduza a Subparte de Duração da Solicitação do Time to First Byte

Este artigo faz parte do nosso guia sobre Time to First Byte (TTFB). A duração da solicitação é a quinta e última subparte do TTFB. Ela mede o tempo que seu servidor gasta de fato processando uma solicitação: recebendo-a, executando a lógica da aplicação, consultando bancos de dados e gerando a resposta HTML. De todas as subpartes do TTFB, a duração da solicitação é a que você tem mais controle. Na minha experiência auditando sites com o CoreDash, é o maior contribuinte individual para um TTFB lento na maioria dos sites.

O Time to First Byte (TTFB) pode ser dividido nas seguintes subpartes:

Procurando otimizar o Time to First Byte? Este artigo foca na parte da duração da solicitação do Time to First Byte. Se você não tem certeza do que significa duração da solicitação, comece primeiro com o que é o Time to First Byte e a identificação e correção de problemas de TTFB.

O Que Acontece Durante a Duração da Solicitação

A duração da solicitação começa no momento em que o servidor recebe a solicitação HTTP e termina quando ele envia o primeiro byte da resposta de volta. Tudo o que o seu servidor faz nesse intervalo conta para a duração da solicitação. Em um site dinâmico típico, isso inclui:

  1. Roteamento da solicitação: o servidor web (Nginx, Apache, IIS) recebe a solicitação e a encaminha para a camada da aplicação.
  2. Inicialização da aplicação: o framework é inicializado. No WordPress, isso significa carregar o núcleo, os plugins ativos e o tema. No Node.js/Express, isso significa a execução de middlewares.
  3. Lógica de negócios: o código da sua aplicação é executado: verificações de autenticação, validação de permissões, transformação de dados, seleção de templates.
  4. Consultas ao banco de dados: a aplicação consulta o MySQL, PostgreSQL, MongoDB ou qualquer armazenamento de dados que você utilize. Esta costuma ser a etapa mais lenta.
  5. Geração da resposta: a aplicação renderiza a resposta HTML (ou JSON) a partir de templates, árvores de componentes ou lógica de serialização.

Cada uma dessas etapas adiciona tempo. Um servidor bem otimizado conclui toda a cadeia em menos de 100 ms. Um mal otimizado pode levar 800 ms ou mais, e isso antes mesmo que DNS, conexão e latência de rede entrem em cena.

Como Medir a Duração da Solicitação com a Server-Timing API

O cabeçalho HTTP Server-Timing é a melhor ferramenta para diagnosticar a duração da solicitação. Ele permite que você envie detalhamentos de tempo do servidor diretamente para o navegador, onde eles aparecem no DevTools e ficam acessíveis via Performance API. Isso significa que você pode medir etapas individuais (consultas ao banco de dados, renderização de templates, buscas em cache) e ver exatamente o que está lento.

O formato do cabeçalho Server-Timing é:

Server-Timing: db;dur=53.2;desc="Database queries",
               app;dur=24.1;desc="Application logic",
               tpl;dur=18.7;desc="Template rendering"

Esses valores aparecem no painel de Rede (Network) do Chrome DevTools, na guia "Timing", fornecendo um waterfall do lado do servidor que mapeia diretamente para o seu código.

Server-Timing no PHP

A função hrtime(true) do PHP fornece precisão de nanossegundos, tornando-a ideal para medir operações individuais do lado do servidor. Veja como adicionar Server-Timing a uma aplicação PHP:

// Mede o tempo da consulta ao banco de dados com precisão de nanossegundos
$dbStart = hrtime(true);
$result = $pdo->query('SELECT * FROM products WHERE active = 1');
$dbDuration = (hrtime(true) - $dbStart) / 1e6; // Converte para ms

// Mede a renderização do template
$tplStart = hrtime(true);
$html = renderTemplate('product-list', ['products' => $result]);
$tplDuration = (hrtime(true) - $tplStart) / 1e6;

// Envia o cabeçalho Server-Timing para o navegador
header(sprintf(
    'Server-Timing: db;dur=%.1f;desc="Database", tpl;dur=%.1f;desc="Template"',
    $dbDuration,
    $tplDuration
));

Server-Timing no Node.js / Express

No Node.js, use process.hrtime.bigint() para cronometragem de alta resolução. Um padrão de middleware permite medir o tempo total de processamento da solicitação e as operações individuais:

// Middleware do Express para cabeçalhos Server-Timing
app.use((req, res, next) => {
  const start = process.hrtime.bigint();
  const timings = [];

  // Anexa um auxiliar ao objeto de resposta
  res.serverTiming = (name, desc) => {
    const mark = process.hrtime.bigint();
    return () => {
      const dur = Number(process.hrtime.bigint() - mark) / 1e6;
      timings.push(`${name};dur=${dur.toFixed(1)};desc="${desc}"`);
    };
  };

  // Antes de enviar a resposta, adiciona o cabeçalho
  const originalEnd = res.end.bind(res);
  res.end = (...args) => {
    const total = Number(process.hrtime.bigint() - start) / 1e6;
    timings.push(`total;dur=${total.toFixed(1)};desc="Total"`);
    res.setHeader('Server-Timing', timings.join(', '));
    originalEnd(...args);
  };

  next();
});

// Uso em um manipulador de rota
app.get('/products', async (req, res) => {
  const endDb = res.serverTiming('db', 'Database');
  const products = await db.query('SELECT * FROM products');
  endDb();

  const endTpl = res.serverTiming('tpl', 'Template');
  const html = renderTemplate('products', { products });
  endTpl();

  res.send(html);
});

Gargalos Comuns na Duração da Solicitação

Após instrumentar centenas de servidores, vejo os mesmos gargalos repetidamente. Aqui estão as causas mais comuns para uma duração de solicitação lenta, classificadas pela frequência com que as encontro:

  • Consultas lentas ao banco de dados: consultas não indexadas, padrões de consulta N+1, varreduras completas de tabelas em tabelas grandes. Esta é a principal causa. A falta de um único índice em uma tabela de produtos do WooCommerce pode adicionar de 300 a 500 ms por solicitação.
  • Falta de cache de página: regenerar o mesmo HTML para cada visitante quando o conteúdo não mudou. Isso é especialmente comum em sites WordPress sem um cache de objeto ou plugin de cache de página.
  • Computações custosas: executar cálculos complexos, processamento de imagens ou agregação de dados a cada solicitação em vez de armazenar os resultados em cache.
  • Chamadas de API externas: solicitações síncronas para APIs de terceiros (gateways de pagamento, sistemas de CRM, serviços de inventário) que bloqueiam a resposta até serem concluídas.
  • Código de aplicação não otimizado: carregar módulos não utilizados, executar middlewares desnecessários ou usar algoritmos ineficientes para o processamento de dados.
  • Cold starts (inicializações a frio): em plataformas serverless (AWS Lambda, Cloudflare Workers, Vercel Functions), a primeira solicitação após um período de inatividade incorre em uma sobrecarga de inicialização do contêiner.

Soluções Específicas por Plataforma

WordPress

Sites WordPress são particularmente vulneráveis a uma duração de solicitação lenta porque cada carregamento de página inicializa todo o núcleo do WordPress, todos os plugins ativos e o tema. Eis o que faz a maior diferença:

  • Instale um cache de objeto persistente: Redis ou Memcached. O WordPress executa dezenas de consultas ao banco de dados por carregamento de página, muitas delas idênticas entre os visitantes. Um cache de objeto (através de um plugin como o Redis Object Cache) armazena esses resultados na memória, reduzindo o tempo do banco de dados em 60 a 80%.
  • Habilite o cache de página inteira: use um cache de página em nível de servidor (Nginx FastCGI Cache, Varnish) ou um plugin como o WP Super Cache. Isso serve o HTML em cache diretamente, sem sequer tocar no PHP.
  • Audite plugins lentos: use o plugin Query Monitor para identificar quais plugins estão gerando a maioria das consultas ao banco de dados ou consumindo a maior parte do tempo de execução do PHP.
  • Otimize as consultas do WooCommerce: O WooCommerce é notório por consultas lentas de produtos. Habilite o recurso High-Performance Order Storage (HPOS) e adicione índices de banco de dados adequados à tabela wp_postmeta.

Estudo de caso: Um site WordPress reduziu a duração da solicitação de 800 ms para 120 ms implementando cache de objeto (Redis) e otimizando uma consulta lenta de produto do WooCommerce que estava sendo executada em todos os carregamentos de página. A consulta de produto sozinha representava 450 ms porque estava fazendo uma varredura completa na tabela em 80.000 linhas de postmeta sem um índice.

Node.js

Aplicações Node.js normalmente têm uma duração de solicitação rápida nativamente, mas problemas aparecem em escala ou com operações de bloqueio:

  • Crie perfis com o inspetor integrado: execute node --inspect app.js e conecte o Chrome DevTools para identificar funções que exigem muito da CPU. Procure por operações síncronas que bloqueiam o event loop.
  • Habilite o log de consultas do ORM: se você usar Sequelize, Prisma ou TypeORM, habilite o log de consultas para encontrar padrões N+1 e consultas lentas. No Sequelize: sequelize = new Sequelize({ logging: console.log }).
  • Use pool de conexões (connection pooling): não crie uma nova conexão de banco de dados para cada solicitação. Use um pool de conexões (integrado à maioria dos drivers de banco de dados do Node.js) para reutilizar conexões.
  • Implemente cache em memória: para dados acessados com frequência que não mudam muito, use um cache LRU para evitar consultar o banco de dados a cada solicitação.

PHP (não-WordPress)

Para Laravel, Symfony ou aplicações PHP personalizadas:

  • Habilite o OPcache: O OPcache do PHP compila scripts PHP em bytecode e os armazena na memória compartilhada, eliminando a necessidade de analisar e compilar a cada solicitação. Só isso já pode reduzir a duração da solicitação em 30 a 50%.
  • Use um preloader de bytecode: O PHP 8.0+ suporta preloading (disponível desde o PHP 7.4), que carrega os arquivos do framework na memória na inicialização do servidor, de forma que não precisam ser carregados por solicitação.
  • Crie perfis com Xdebug ou Blackfire: identifique as funções específicas que consomem a maior parte do tempo de relógio (wall-clock time).

Python (Django / Flask)

Aplicações Python costumam ter uma duração de solicitação base mais alta em comparação ao Node.js ou PHP:

  • Use um framework assíncrono: se a espera de E/S for o gargalo, considere o FastAPI ou o Django com ASGI para lidar com consultas ao banco de dados e chamadas de API simultaneamente.
  • Habilite o log de consultas de banco de dados do Django: defina LOGGING nas configurações para registrar todas as consultas SQL e identificar as lentas ou redundantes.
  • Use select_related() e prefetch_related(): o ORM do Django vai gerar consultas N+1 alegremente, a menos que você diga explicitamente para ele unir as tabelas relacionadas (join).

Pool de Conexões de Banco de Dados

Abrir uma nova conexão de banco de dados para cada solicitação é uma das causas mais comuns e mais evitáveis de uma duração de solicitação lenta. Cada nova conexão requer um handshake TCP, autenticação e inicialização da sessão, o que pode adicionar de 5 a 30 ms por solicitação. Sob carga, isso se torna catastrófico quando o servidor de banco de dados fica sem conexões disponíveis.

O pool de conexões (connection pooling) resolve isso mantendo um pool de conexões abertas que são reutilizadas em diferentes solicitações. A aplicação empresta uma conexão do pool, executa suas consultas e devolve a conexão quando termina. Isso elimina totalmente a sobrecarga de conexão por solicitação.

A maioria dos drivers de banco de dados suporta pool de conexões nativamente. No Node.js com pg (PostgreSQL), por exemplo, configure-o desta forma:

const { Pool } = require('pg');

const pool = new Pool({
  host: 'localhost',
  database: 'myapp',
  max: 20,        // Máximo de conexões no pool
  idleTimeoutMillis: 30000,  // Fecha conexões ociosas após 30s
  connectionTimeoutMillis: 2000  // Falha rápido se não houver conexão disponível
});

// Use pool.query() em vez de criar novos clientes
const result = await pool.query('SELECT * FROM products WHERE id = $1', [id]);

Para aplicações PHP por trás do PHP-FPM, considere usar conexões persistentes (PDO::ATTR_PERSISTENT) ou um pooler externo como o PgBouncer para PostgreSQL ou o ProxySQL para MySQL.

Cache de Proxy Reverso

A resposta mais rápida é aquela que a sua aplicação nunca precisa gerar. Um cache de proxy reverso (Varnish, Nginx FastCGI Cache ou um cache de borda de CDN) fica na frente do servidor da sua aplicação e serve as respostas em cache diretamente da memória. Para páginas que não mudam de um visitante para outro (o que inclui a maioria das páginas na maior parte dos sites), isso reduz a duração da solicitação a quase zero.

  • Varnish: um cache HTTP dedicado que pode servir milhares de solicitações por segundo a partir da memória. Configure os cabeçalhos Cache-Control nas respostas da sua aplicação e o Varnish cuida do resto.
  • Nginx FastCGI Cache: se você já usa o Nginx como seu servidor web, habilite o seu cache integrado para as respostas do PHP-FPM. Isso evita adicionar outra camada à sua stack.
  • Cache de borda de CDN (Edge caching): serviços como Cloudflare, Fastly e Amazon CloudFront podem armazenar em cache o seu HTML em locais de borda em todo o mundo, reduzindo simultaneamente a duração da solicitação e a latência da rede.

A chave para um cache de proxy reverso eficaz são os cabeçalhos Cache-Control adequados. Defina s-maxage para o TTL do cache compartilhado e use stale-while-revalidate para servir o conteúdo obsoleto enquanto o cache está sendo atualizado em segundo plano:

Cache-Control: public, s-maxage=3600, stale-while-revalidate=60

Edge Computing para Duração da Solicitação

Plataformas de Edge computing, como Cloudflare Workers e Vercel Edge Functions, executam seu código do lado do servidor em locais de borda de CDN, fisicamente próximos aos seus usuários. O Edge computing não deixará o seu código mais rápido, mas elimina a latência da rede entre o usuário e o seu servidor de origem. Isso é mais importante para usuários distantes do seu data center de origem.

Edge functions funcionam melhor para:

  • Respostas leves de API que não requerem acesso pesado ao banco de dados
  • Lógica de personalização (testes A/B, conteúdo baseado em geolocalização) aplicada na borda antes de atingir a sua origem
  • Reescritas de HTML e manipulação de cabeçalhos sem uma viagem de ida e volta completa até a origem

Para páginas que exigem consultas ao banco de dados, o Edge computing por si só não resolverá os problemas de duração da solicitação. A grande vantagem é combinar Edge functions com um banco de dados distribuído globalmente (PlanetScale, Neon, Turso) ou cache no lado da borda para manter o ciclo de vida completo da solicitação próximo ao usuário.

Medindo a Duração da Solicitação com JavaScript

Você pode medir a subparte de duração da solicitação do TTFB diretamente no navegador usando a Navigation Timing API:

new PerformanceObserver((entryList) => {
  const [nav] = entryList.getEntriesByType('navigation');

  const requestDuration = nav.responseStart - nav.requestStart;

  console.log('Request Duration:', requestDuration.toFixed(0), 'ms');
  console.log('  Request start:', nav.requestStart.toFixed(0), 'ms');
  console.log('  Response start:', nav.responseStart.toFixed(0), 'ms');

  if (requestDuration > 200) {
    console.warn('Duração de solicitação lenta detectada. Verifique o tempo de processamento do servidor.');
  }
}).observe({
  type: 'navigation',
  buffered: true
});

A duração da solicitação é calculada como responseStart - requestStart. Um valor consistentemente acima de 200 ms indica que o seu servidor está gastando muito tempo processando a solicitação. Use o cabeçalho Server-Timing (descrito acima) para identificar qual parte do processamento do servidor é a responsável.

Como Identificar Problemas de Duração da Solicitação com Dados de RUM

Para entender como a duração da solicitação afeta seus usuários reais, você precisa de uma ferramenta de Real User Monitoring (RUM) como o CoreDash. Os dados de RUM mostram o detalhamento real do TTFB que seus visitantes experimentam em todas as páginas, dispositivos e locais. Não os resultados de laboratório.

No CoreDash, clique em "Time to First Byte breakdown" para visualizar a porção da duração da solicitação do TTFB. Procure por páginas em que a duração da solicitação está consistentemente acima de 200 ms. Esses são os seus alvos de otimização.

O Que os Nossos Dados Mostram

Em milhares de sites monitorados pelo CoreDash, a duração da solicitação (tempo de processamento do servidor) é a maior subparte do TTFB na maioria dos sites em nosso conjunto de dados, tornando a otimização do servidor a maior melhoria individual do TTFB para a maioria dos sites.

Sites com cache de página inteira ativado têm uma duração de solicitação mediana de aproximadamente 35 ms. Sites sem qualquer cache têm uma mediana de aproximadamente 320 ms. Essa diferença (quase 10x) é o argumento mais forte que posso apresentar para investir em cache no lado do servidor antes de qualquer outra coisa.

A duração da solicitação é parte do Time to First Byte, que é uma métrica de diagnóstico para os Core Web Vitals. Para um guia completo sobre como identificar e corrigir problemas de TTFB, consulte nosso guia de identificação e correção de TTFB. Você também pode conferir o checklist definitivo dos Core Web Vitals para uma visão geral abrangente da otimização.

Leitura Adicional: Guias de Otimização

Para técnicas de otimização relacionadas que complementam a otimização da duração da solicitação, explore estes guias:

  • 103 Early Hints: envie dicas de recursos (preload, preconnect) para o navegador enquanto o servidor ainda está processando a solicitação, reduzindo o TTFB percebido.
  • Configure o Cloudflare para Desempenho: use o cache de borda de CDN e configurações de servidor otimizadas para reduzir a duração da solicitação globalmente.

Subpartes do TTFB: Guias Completos

A duração da solicitação é uma de cinco subpartes do TTFB. Explore as outras subpartes para entender o quadro completo:

Seu site vai passar nos Core Web Vitals.

Mais de 500 mil páginas para grandes publishers europeus e plataformas de e-commerce. Escrevo os fixes e confirmo tudo com dados de campo.

Como eu trabalho
Duração da Solicitação do TTFB: Reduza o Tempo de Processamento do ServidorCore Web Vitals Duração da Solicitação do TTFB: Reduza o Tempo de Processamento do Servidor