TTFB: Porque é que o Time To First Byte é importante tanto para o SEO como para os LLMs

O Time To First Byte (TTFB) é uma das métricas de desempenho mais críticas, embora frequentemente negligenciada, para websites. Embora a maioria se concentre no tempo de carregamento da página ou na renderização visual, o TTFB é o primeiro indicador de quão responsivo é o seu site — e isso é importante tanto para os motores de busca como para os crawlers de IA. Um TTFB lento pode significar que os sistemas de IA rastreiam menos páginas, priorizam o seu conteúdo mais abaixo ou desistem totalmente de rastrear o seu site. Este guia explica o que é o TTFB, por que motivo é importante e como otimizá-lo.

TTFB: Porque é que o Time To First Byte é importante tanto para o SEO como para os LLMs

Publicado em

Autor

Jakob Langemark

Siga-nos

TTFB: Porque o Time To First Byte é importante tanto para SEO como para LLMs

O Time To First Byte (TTFB) é uma das métricas de desempenho mais críticas, porém negligenciadas, para websites. Embora a maioria se foque no tempo de carregamento da página ou na renderização visual, o TTFB é o primeiro indicador do quão responsivo o seu site é — e isso importa tanto para os motores de busca como para os crawlers de IA. Um TTFB lento pode significar que os sistemas de IA rastreiam menos páginas, priorizam o seu conteúdo mais abaixo ou desistem completamente de rastrear o seu site. Este guia explica o que é o TTFB, por que é importante e como otimizá-lo.

O que é o TTFB?

O Time To First Byte (TTFB) é o tempo desde que um navegador/crawler envia um pedido HTTP até receber o primeiro byte de dados do servidor.

Componentes do TTFB:

  1. Pesquisa de DNS — Tempo para traduzir o nome de domínio em endereço IP

  2. Tempo de ligação — Tempo para estabelecer a ligação TCP

  3. Handshake SSL/TLS — Tempo para estabelecer a ligação HTTPS (se aplicável)

  4. Tempo de processamento do servidor — Tempo que o servidor demora a gerar a resposta

  5. Latência de rede — Tempo que o primeiro byte demora a regressar

Fórmula:

TTFB vs. outras métricas

O TTFB mede a capacidade de resposta do servidor antes de qualquer conteúdo ser enviado.

O FCP (First Contentful Paint) mede quando o primeiro conteúdo visual é renderizado.

O LCP (Largest Contentful Paint) mede quando o elemento principal é carregado.

O TTFB acontece primeiro — é a base para todas as outras métricas de carregamento.

Por que o TTFB é importante para crawlers de IA

1. Orçamentos de rastreio (crawl budgets)

Os crawlers de IA (e motores de busca) têm um tempo limitado por site. Se o seu TTFB for lento, eles rastreiam menos páginas antes que o seu orçamento de tempo se esgote.

Exemplo:

  • Site A: TTFB = 200ms → O crawler consegue rastrear 500 páginas em 5 minutos

  • Site B: TTFB = 2000ms → O crawler apenas consegue rastrear 150 páginas em 5 minutos

O Site A obtém 3x mais cobertura de rastreio.

2. Priorização de rastreio

Os crawlers priorizam sites rápidos. Se o seu TTFB for consistentemente lento, os crawlers irão:

  • Regressar com menos frequência

  • Rastrear menos páginas por visita

  • Priorizar os sites dos concorrentes

3. Qualidade dos dados

Um TTFB longo pode resultar em timeouts. A IA obtém dados incompletos ou desiste por completo.

Orientação da Google:

  • TTFB Bom: < 600ms

  • TTFB Aceitável: 600ms - 1200ms

  • TTFB Mau: > 1200ms

O mesmo se aplica aos crawlers de IA.

Porque o TTFB também é importante para o SEO

A Google confirmou indiretamente que o TTFB é um fator de posicionamento através dos Core Web Vitals (afeta o LCP).

Impacto:

  • TTFB lento → LCP lento → Pior posicionamento

  • TTFB rápido → LCP rápido → Melhor posicionamento

Meça o seu TTFB atual

Ferramentas de Programador do Navegador (Chrome DevTools)

  1. Abra o Chrome DevTools (F12)

  2. Aceda ao separador Rede (Network)

  3. Atualize a página

  4. Clique no primeiro pedido (normalmente o seu documento HTML)

  5. Consulte o separador Tempo (Timing)

Irá ver:




PageSpeed Insights

  1. Aceda a https://pagespeed.web.dev/

  2. Introduza o seu URL

  3. Veja "Tempo de resposta do servidor" em diagnósticos

WebPageTest

  1. Aceda a https://www.webpagetest.org/

  2. Introduza o seu URL e selecione a localização do teste

  3. Veja "Time to First Byte" nos resultados

O WebPageTest também mostra:

  • TTFB por pedido (não apenas o primeiro HTML)

  • Detalhamento de DNS, Ligação, SSL, Espera

Teste em linha de comandos com curl

# Medir o TTFB
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nLigação: %{time_connect}s\nSSL: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://ditwebsite.dk/

# Resultado:
# DNS: 0.015s
# Ligação: 0.045s
# SSL: 0.132s
# TTFB: 0.456s
# Total: 0.612s
# Medir o TTFB
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nLigação: %{time_connect}s\nSSL: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://ditwebsite.dk/

# Resultado:
# DNS: 0.015s
# Ligação: 0.045s
# SSL: 0.132s
# TTFB: 0.456s
# Total: 0.612s
# Medir o TTFB
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nLigação: %{time_connect}s\nSSL: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://ditwebsite.dk/

# Resultado:
# DNS: 0.015s
# Ligação: 0.045s
# SSL: 0.132s
# TTFB: 0.456s
# Total: 0.612s

Script Python para testes em lote

import requests
import time

def measure_ttfb(url):
    start = time.time()
    r = requests.get(url, stream=True)
    ttfb = time.time() - start
    return ttfb * 1000  # Converter para milissegundos

urls = [
    "https://ditwebsite.dk/",
    "https://ditwebsite.dk/products/",
    "https://ditwebsite.dk/blog/"
]

for url in urls:
    ttfb = measure_ttfb(url)
    print(f"{url}: {ttfb:.2f}ms")
import requests
import time

def measure_ttfb(url):
    start = time.time()
    r = requests.get(url, stream=True)
    ttfb = time.time() - start
    return ttfb * 1000  # Converter para milissegundos

urls = [
    "https://ditwebsite.dk/",
    "https://ditwebsite.dk/products/",
    "https://ditwebsite.dk/blog/"
]

for url in urls:
    ttfb = measure_ttfb(url)
    print(f"{url}: {ttfb:.2f}ms")
import requests
import time

def measure_ttfb(url):
    start = time.time()
    r = requests.get(url, stream=True)
    ttfb = time.time() - start
    return ttfb * 1000  # Converter para milissegundos

urls = [
    "https://ditwebsite.dk/",
    "https://ditwebsite.dk/products/",
    "https://ditwebsite.dk/blog/"
]

for url in urls:
    ttfb = measure_ttfb(url)
    print(f"{url}: {ttfb:.2f}ms")

Identifique o que torna o seu TTFB lento

O TTFB divide-se em vários componentes. Identifique os estrangulamentos:

1. Pesquisa de DNS (deve ser < 20ms)

Problema: Resolvedor de DNS lento.

Teste:

Solução:

  • Utilize um fornecedor de DNS rápido (Cloudflare DNS, Google DNS)

  • Ative a pré-procura de DNS (DNS prefetching):

<link rel="dns-prefetch" href="//ditwebsite.dk">
<link rel="dns-prefetch" href="//ditwebsite.dk">
<link rel="dns-prefetch" href="//ditwebsite.dk">

2. Tempo de ligação (deve ser < 50ms)

Problema: Distância geográfica ao servidor ou rede lenta.

Solução:

  • Utilize uma Rede de Distribuição de Conteúdo (CDN) para estar mais perto dos utilizadores/crawlers

  • Reduza o número de ligações (o HTTP/2 ajuda)

3. Handshake SSL/TLS (deve ser < 100ms)

Problema: Negociação SSL lenta.

Teste:

openssl s_time -connect ditwebsite.dk:443 -www
openssl s_time -connect ditwebsite.dk:443 -www
openssl s_time -connect ditwebsite.dk:443 -www

Solução:

  • Ative o TLS 1.3 (handshake mais rápido)

  • Utilize grampeamento OCSP (OCSP stapling)

  • Ative o HTTP/2 ou HTTP/3

4. Tempo de processamento do servidor (deve ser < 200ms)

Problema: Backend lento ou consultas de base de dados lentas.

Este é normalmente o maior estrangulamento.

Identificar:

  • Verifique os registos do servidor para identificar pedidos lentos

  • Utilize ferramentas APM (New Relic, Datadog)

  • Analise o perfil das consultas à base de dados

Otimizar o tempo de processamento do servidor

É aqui que consegue o maior impacto.

1. Implementar cache

Cache do lado do servidor (Server-side caching):

Utilize Redis ou Memcached para guardar em cache os resultados da base de dados.

Exemplo (PHP com Redis):

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$cache_key = 'homepage_data';
$data = $redis->get($cache_key);

if (!$data) {
    // Dados não estão na cache, obter da base de dados
    $data = fetch_from_database();
    $redis->setex($cache_key, 3600, serialize($data));  // Cache por 1 hora
} else {
    $data = unserialize($data);
}

echo json_encode($data);

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$cache_key = 'homepage_data';
$data = $redis->get($cache_key);

if (!$data) {
    // Dados não estão na cache, obter da base de dados
    $data = fetch_from_database();
    $redis->setex($cache_key, 3600, serialize($data));  // Cache por 1 hora
} else {
    $data = unserialize($data);
}

echo json_encode($data);

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$cache_key = 'homepage_data';
$data = $redis->get($cache_key);

if (!$data) {
    // Dados não estão na cache, obter da base de dados
    $data = fetch_from_database();
    $redis->setex($cache_key, 3600, serialize($data));  // Cache por 1 hora
} else {
    $data = unserialize($data);
}

echo json_encode($data);

Cache de página inteira (Full-page caching):

Guarde em cache respostas HTML completas.

Exemplo Nginx:

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

server {
    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 60m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_pass http

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

server {
    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 60m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_pass http

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

server {
    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 60m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_pass http

2. Otimizar consultas à base de dados

Problema: Consultas N+1 ou consultas sem índice.

Identificar consultas lentas (MySQL):

-- Ativar o registo de consultas lentas
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- Consultas com mais de 1 segundo

-- Ver consultas lentas
SELECT * FROM

-- Ativar o registo de consultas lentas
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- Consultas com mais de 1 segundo

-- Ver consultas lentas
SELECT * FROM

-- Ativar o registo de consultas lentas
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- Consultas com mais de 1 segundo

-- Ver consultas lentas
SELECT * FROM

Soluções:

  • Adicionar índices:

-- Antes: Varredura completa da tabela (Full table scan)
SELECT * FROM products WHERE category = 'electronics';

-- Depois: Criar índice
CREATE INDEX idx_category ON products(category)

-- Antes: Varredura completa da tabela (Full table scan)
SELECT * FROM products WHERE category = 'electronics';

-- Depois: Criar índice
CREATE INDEX idx_category ON products(category)

-- Antes: Varredura completa da tabela (Full table scan)
SELECT * FROM products WHERE category = 'electronics';

-- Depois: Criar índice
CREATE INDEX idx_category ON products(category)

  • Utilizar cache de consultas (query caching):

-- Ativar cache de consultas (MySQL 5.7)
SET GLOBAL query_cache_size = 67108864;  -- 64MB
SET GLOBAL query_cache_type = ON

-- Ativar cache de consultas (MySQL 5.7)
SET GLOBAL query_cache_size = 67108864;  -- 64MB
SET GLOBAL query_cache_type = ON

-- Ativar cache de consultas (MySQL 5.7)
SET GLOBAL query_cache_size = 67108864;  -- 64MB
SET GLOBAL query_cache_type = ON

  • Otimizar JOINs:

-- Incorreto: Múltiplos joins sem índices adequados
SELECT * FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id
WHERE users.country = 'DK';

-- Correto: Adicionar índices compostos
CREATE INDEX idx_user_country ON users(country, id);
CREATE INDEX idx_product_id ON products(id)

-- Incorreto: Múltiplos joins sem índices adequados
SELECT * FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id
WHERE users.country = 'DK';

-- Correto: Adicionar índices compostos
CREATE INDEX idx_user_country ON users(country, id);
CREATE INDEX idx_product_id ON products(id)

-- Incorreto: Múltiplos joins sem índices adequados
SELECT * FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id
WHERE users.country = 'DK';

-- Correto: Adicionar índices compostos
CREATE INDEX idx_user_country ON users(country, id);
CREATE INDEX idx_product_id ON products(id)

3. Atualizar recursos do servidor

Verificar a carga do servidor:

top
# Ver utilização de CPU e memória

htop
# Alternativa mais fácil de utilizar
top
# Ver utilização de CPU e memória

htop
# Alternativa mais fácil de utilizar
top
# Ver utilização de CPU e memória

htop
# Alternativa mais fácil de utilizar

Se estiver consistentemente alta (>80% CPU):

  • Atualize a CPU

  • Adicione mais RAM

  • Utilize balanceamento de carga (load balancing)

4. Utilizar uma CDN

As Redes de Distribuição de Conteúdo guardam o conteúdo em cache geograficamente perto dos utilizadores/crawlers.

CDNs populares:

  • Cloudflare — Plano gratuito disponível, excelente para sites pequenos e médios

  • AWS CloudFront — Altamente escalável

  • Fastly — Ótimo desempenho, mais técnico

  • BunnyCDN — Económica

Como a CDN melhora o TTFB:

Sem CDN:

  • Um utilizador nos EUA acede a um site alojado na Europa

  • TTFB = 500ms (200ms de latência de rede + 300ms de processamento do servidor)

Com CDN:

  • O utilizador nos EUA faz o pedido → Servidor de borda (edge) da CDN nos EUA

  • TTFB = 150ms (20ms de latência de rede + 130ms de resposta da cache)

5. Ativar compressão Gzip/Brotli

A compressão reduz o tamanho da resposta, acelerando o tempo de transferência.

Configuração Nginx:

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;
gzip_comp_level 6;

# Ainda melhor: Brotli
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;
gzip_comp_level 6;

# Ainda melhor: Brotli
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;
gzip_comp_level 6;

# Ainda melhor: Brotli
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text

Configuração Apache:

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>

6. Reduzir o processamento no lado do servidor

Minimize:

  • Cálculos pesados em cada pedido

  • Chamadas a APIs externas

  • Operações de E/S (I/O) de ficheiros

Exemplo (Python Flask):

from flask import Flask, render_template
from functools import lru_cache
import requests

app = Flask(__name__)

# Incorreto: Chamada a API externa em cada pedido
@app.route('/weather')
def weather_bad():
    response = requests.get('https://api.weather.com/data')
    return render_template('weather.html', data=response.json())

# Correto: Guardar chamada a API externa em cache
@lru_cache(maxsize=128)
def fetch_weather_cached():
    response = requests.get('https://api.weather.com/data')
    return response.json()

@app.route('/weather')
def weather_good():
    data = fetch_weather_cached()
    return render_template('weather.html', data=data)
from flask import Flask, render_template
from functools import lru_cache
import requests

app = Flask(__name__)

# Incorreto: Chamada a API externa em cada pedido
@app.route('/weather')
def weather_bad():
    response = requests.get('https://api.weather.com/data')
    return render_template('weather.html', data=response.json())

# Correto: Guardar chamada a API externa em cache
@lru_cache(maxsize=128)
def fetch_weather_cached():
    response = requests.get('https://api.weather.com/data')
    return response.json()

@app.route('/weather')
def weather_good():
    data = fetch_weather_cached()
    return render_template('weather.html', data=data)
from flask import Flask, render_template
from functools import lru_cache
import requests

app = Flask(__name__)

# Incorreto: Chamada a API externa em cada pedido
@app.route('/weather')
def weather_bad():
    response = requests.get('https://api.weather.com/data')
    return render_template('weather.html', data=response.json())

# Correto: Guardar chamada a API externa em cache
@lru_cache(maxsize=128)
def fetch_weather_cached():
    response = requests.get('https://api.weather.com/data')
    return response.json()

@app.route('/weather')
def weather_good():
    data = fetch_weather_cached()
    return render_template('weather.html', data=data)

7. Utilizar HTTP/2 ou HTTP/3

O HTTP/2 permite multiplexagem, reduzindo a sobrecarga de ligação.

Ativar HTTP/2 (Nginx):

server {
    listen 443 ssl http2;
    server_name ditwebsite.dk;
    # ... resto da configuração

server {
    listen 443 ssl http2;
    server_name ditwebsite.dk;
    # ... resto da configuração

server {
    listen 443 ssl http2;
    server_name ditwebsite.dk;
    # ... resto da configuração

Testar se o HTTP/2 está ativo:

curl -I --http2 https://ditwebsite.dk/
# Procure por "HTTP/2 200" na resposta
curl -I --http2 https://ditwebsite.dk/
# Procure por "HTTP/2 200" na resposta
curl -I --http2 https://ditwebsite.dk/
# Procure por "HTTP/2 200" na resposta

Otimizar especificamente para crawlers de IA

1. Priorizar páginas importantes

Garanta que as suas páginas mais importantes (página inicial, produtos principais, artigos de destaque) têm o TTFB mais rápido.

Nginx: Cache separada para páginas principais:

location = / {
    proxy_cache_valid 200 120m;  # Guardar homepage em cache por 2 horas
    proxy_pass http://backend;
}

location /products/ {
    proxy_cache_valid 200 60m;  # Guardar produtos em cache por 1 hora
    proxy_pass http

location = / {
    proxy_cache_valid 200 120m;  # Guardar homepage em cache por 2 horas
    proxy_pass http://backend;
}

location /products/ {
    proxy_cache_valid 200 60m;  # Guardar produtos em cache por 1 hora
    proxy_pass http

location = / {
    proxy_cache_valid 200 120m;  # Guardar homepage em cache por 2 horas
    proxy_pass http://backend;
}

location /products/ {
    proxy_cache_valid 200 60m;  # Guardar produtos em cache por 1 hora
    proxy_pass http

2. Detetar e otimizar para crawlers

Servir versão em cache para crawlers:

<?php
$user_agent = $_SERVER['HTTP_USER_AGENT'];

$is_crawler = preg_match('/GPTBot|ClaudeBot|CCBot|Googlebot|bingbot/i', $user_agent);

if ($is_crawler) {
    // Servir HTML estático em cache
    echo file_get_contents('/cache/static_page.html');
} else {
    // Servir conteúdo dinâmico
    include('dynamic_page.php');
}

<?php
$user_agent = $_SERVER['HTTP_USER_AGENT'];

$is_crawler = preg_match('/GPTBot|ClaudeBot|CCBot|Googlebot|bingbot/i', $user_agent);

if ($is_crawler) {
    // Servir HTML estático em cache
    echo file_get_contents('/cache/static_page.html');
} else {
    // Servir conteúdo dinâmico
    include('dynamic_page.php');
}

<?php
$user_agent = $_SERVER['HTTP_USER_AGENT'];

$is_crawler = preg_match('/GPTBot|ClaudeBot|CCBot|Googlebot|bingbot/i', $user_agent);

if ($is_crawler) {
    // Servir HTML estático em cache
    echo file_get_contents('/cache/static_page.html');
} else {
    // Servir conteúdo dinâmico
    include('dynamic_page.php');
}

3. Pré-aquecer a cache antes das visitas dos crawlers

Se souber quando os crawlers visitam (por exemplo, após o envio do sitemap), pré-aqueça a cache:

#!/bin/bash
# Aquecer a cache solicitando todos os URLs
while read url; do
  curl -s "$url" > /dev/null
done

#!/bin/bash
# Aquecer a cache solicitando todos os URLs
while read url; do
  curl -s "$url" > /dev/null
done

#!/bin/bash
# Aquecer a cache solicitando todos os URLs
while read url; do
  curl -s "$url" > /dev/null
done

Monitorizar o TTFB continuamente

Configurar monitorização automática

Pingdom:

  1. Crie uma conta em pingdom.com

  2. Adicione verificações de URL

  3. Defina o limite de alerta (ex.: "alertar se TTFB > 800ms")

UptimeRobot:

  1. Monitorização gratuita a cada 5 minutos

  2. Alertas por e-mail

Script personalizado (cron job):

#!/bin/bash
# Verificar o TTFB e alertar se for > 1000ms
TTFB=$(curl -o /dev/null -s -w '%{time_starttransfer}' https://ditwebsite.dk/)
TTFB_MS=$(echo "$TTFB * 1000" | bc)

if (( $(echo "$TTFB_MS > 1000" | bc -l) )); then
  echo "TTFB demasiado alto: ${TTFB_MS}ms" | mail -s "Alerta de TTFB" admin@ditwebsite.dk
fi
#!/bin/bash
# Verificar o TTFB e alertar se for > 1000ms
TTFB=$(curl -o /dev/null -s -w '%{time_starttransfer}' https://ditwebsite.dk/)
TTFB_MS=$(echo "$TTFB * 1000" | bc)

if (( $(echo "$TTFB_MS > 1000" | bc -l) )); then
  echo "TTFB demasiado alto: ${TTFB_MS}ms" | mail -s "Alerta de TTFB" admin@ditwebsite.dk
fi
#!/bin/bash
# Verificar o TTFB e alertar se for > 1000ms
TTFB=$(curl -o /dev/null -s -w '%{time_starttransfer}' https://ditwebsite.dk/)
TTFB_MS=$(echo "$TTFB * 1000" | bc)

if (( $(echo "$TTFB_MS > 1000" | bc -l) )); then
  echo "TTFB demasiado alto: ${TTFB_MS}ms" | mail -s "Alerta de TTFB" admin@ditwebsite.dk
fi

Executar a cada hora:

crontab -e
# Adicionar:
0

crontab -e
# Adicionar:
0

crontab -e
# Adicionar:
0

Metas de TTFB

Recomendações da Google

  • Bom: < 600ms

  • Necessita de melhorias: 600ms - 1200ms

  • Fraco: > 1200ms

Para crawlers de IA (recomendações)

  • Excelente: < 300ms (obtém a maior prioridade de rastreio)

  • Bom: 300ms - 600ms (taxa de rastreio normal)

  • Aceitável: 600ms - 1000ms (taxa de rastreio mais baixa)

  • Fraco: > 1000ms (risco de rastreios incompletos)

Problemas comuns de TTFB e soluções

Problema

Sintoma

Solução

Sem cache

TTFB > 1000ms em todos os pedidos

Implementar Redis/Memcached

Base de dados lenta

TTFB alto em páginas dinâmicas

Adicionar índices, otimizar consultas

Sem CDN

TTFB alto para tráfego internacional

Ativar Cloudflare ou AWS CloudFront

Sobrecarga do servidor

Picos de TTFB durante picos de tráfego

Aumentar recursos do servidor ou adicionar balanceamento de carga

Código não otimizado

TTFB inconsistente

Analisar perfil do código, remover estrangulamentos

Chamadas de API externas

TTFB alto, variável

Guardar respostas da API em cache, usar chamadas assíncronas

Lista de verificação para implementação

Utilize esta lista para melhorar o seu TTFB:

  1. Medir o TTFB de base — Use PageSpeed Insights ou WebPageTest

  2. Identificar o estrangulamento — DNS, ligação, SSL ou processamento do servidor?

  3. Implementar cache do lado do servidor — Redis/Memcached para resultados de bases de dados

  4. Ativar cache de página inteira — Para páginas estáticas ou semi-estáticas

  5. Otimizar consultas à base de dados — Adicionar índices, remover consultas N+1

  6. Ativar Gzip/Brotli — Comprimir respostas

  7. Utilizar CDN — Cloudflare, AWS CloudFront ou BunnyCDN

  8. Ativar HTTP/2 — Reduzir sobrecarga de ligação

  9. Monitorizar o TTFB — Configurar Pingdom ou monitorização personalizada

  10. Testar com curl — Verificar as melhorias

Conclusão

O TTFB é uma métrica crítica tanto para SEO como para a visibilidade em sistemas de IA. Um TTFB lento significa menos páginas rastreadas, menor prioridade de rastreio e dados potencialmente incompletos para os modelos de IA. A maioria dos sites pode melhorar o seu TTFB com cache (no servidor e de página inteira), otimização de base de dados e o uso de uma CDN.

Comece por medir o seu TTFB atual, identifique o maior estrangulamento (normalmente o processamento do servidor) e implemente cache. Para a maioria dos sites, é possível obter valores abaixo dos 600ms com otimização básica, e abaixo dos 300ms com CDN e cache agressiva.

Lembre-se: o TTFB é a fundação — todas as outras métricas de desempenho dependem dele. Otimize o TTFB primeiro, e só depois o FCP e o LCP.