Compressão HTTP em 2026: Brotli, Zstandard e Compression Dictionary Transport

Guia prático de compressão HTTP em 2026: Brotli, Zstandard e Compression Dictionary Transport, com exemplos de configuração para Nginx, Cloudflare e Fastly, além de scripts de auditoria e comparativos por CDN.

Compressão HTTP 2026: Brotli, Zstd e CDT

Atualizado: 4 de agosto de 2026

A compressão HTTP em 2026 combina três algoritmos principais (gzip, Brotli e Zstandard) negociados pelo cabeçalho Accept-Encoding para reduzir entre 60% e 85% o tamanho de transferência de HTML, CSS, JavaScript e JSON. Brotli continua sendo o padrão para conteúdo estático pré-comprimido, Zstd domina o tráfego dinâmico com tempo de compressão até 4× mais rápido que Brotli, e o novo Compression Dictionary Transport permite deltas entre versões de bundles, cortando payloads de deploy em até 90%. Este guia mostra como configurar, medir e escolher entre eles em Nginx, Cloudflare e Fastly com exemplos executáveis.

  • Brotli nível 11 gera arquivos 15 a 25% menores que gzip 9 para HTML e JS, mas comprimir on-the-fly custa 100× mais CPU. Sempre pré-comprima assets estáticos.
  • Zstandard (RFC 8878) é suportado desde Chrome 123 e Firefox 126; oferece a melhor relação velocidade/ratio para respostas dinâmicas comprimidas por request.
  • Compression Dictionary Transport (Chrome 123+) usa uma versão anterior do bundle como dicionário, reduzindo o tamanho de patches em 70 a 90%.
  • O cabeçalho Vary: Accept-Encoding é obrigatório em CDNs que compartilham cache entre clientes com suporte diferente a codificações.
  • Compressão só afeta o tamanho de transferência, não o tempo de resposta do servidor. Reduza o TTFB antes de mirar em ratio máximo.
  • Nunca comprima assets já comprimidos: WebP, AVIF, MP4, WOFF2 e ZIP têm ratio < 1% e desperdiçam CPU.

Por que a compressão HTTP importa para performance

Compressão reduz bytes na rede. Menos bytes significa menos tempo até o navegador conseguir parsear e renderizar, impactando diretamente o TTFB percebido, o LCP e o volume de dados em conexões móveis. Em uma amostra do HTTP Archive de julho de 2026, a mediana de resposta HTML comprimida está em 8 KB (Brotli) contra 32 KB sem compressão. É uma economia de 75% que se traduz em ~120 ms a menos em 4G lento.

No meu último projeto, um SaaS B2B com bundles JavaScript pesados, pré-comprimir os assets em Brotli-11 no build cortou o LCP mediano em 380 ms sem tocar em uma linha de código do aplicativo. Foi a melhoria de maior ROI de todo o trimestre.

Comprimir todos os recursos de texto (HTML, CSS, JS, JSON, SVG, XML) melhora dois indicadores críticos: o tempo total de download da rota crítica e o uso de dados do usuário, algo especialmente relevante em mercados emergentes e para usuários com Save-Data: on. Recursos binários já comprimidos (imagens, vídeos, fontes WOFF2) não devem ser recomprimidos: você paga CPU e não ganha bytes.

Vale distinguir compressão de transporte (o que este artigo cobre) de compressão de conteúdo (minificação, tree-shaking). A primeira acontece por request e é reversível; a segunda é feita no build e altera o payload original. Ambas se somam: um bundle já minificado e com tree shaking ainda deve ser servido com Brotli ou Zstd.

gzip, Brotli e Zstandard: comparação técnica

Os três algoritmos aceitos por navegadores modernos têm perfis distintos. gzip (DEFLATE, RFC 1952) existe desde 1993, é o baseline universal e o mais rápido para comprimir sob demanda. Brotli (RFC 7932) foi criado pelo Google em 2015 e usa um dicionário estático de 120 KB otimizado para texto da web (daí seus ratios superiores em HTML/CSS/JS). Zstandard, formalizado no RFC 8878, chegou aos navegadores em 2024 e domina em velocidade de descompressão.

CaracterísticagzipBrotliZstandard
Token no Content-Encodinggzipbrzstd
Suporte em navegadores (2026)100%~97%~88%
Ratio típico (HTML 100 KB)72%78%76%
Velocidade de compressão (nível máx)LentaMuito lentaRápida
Velocidade de descompressãoRápidaRápidaMuito rápida
Níveis1–90–111–22
Melhor usoFallback legacyEstático pré-comprimidoDinâmico on-the-fly

Em números reais: comprimir o bundle react-dom.production.min.js (aprox. 130 KB) resulta em 41 KB (gzip -9), 34 KB (brotli -11) e 36 KB (zstd -19). A diferença absoluta parece pequena. Só que num page load típico com 8 a 12 recursos de texto, Brotli economiza 40 a 80 KB, o suficiente para adiantar o LCP em 200 a 400 ms em conexões 3G.

Como o navegador negocia a codificação

O cliente envia:

GET /assets/app.js HTTP/2
Accept-Encoding: zstd, br, gzip

O servidor escolhe a melhor codificação que suporta e responde com:

HTTP/2 200
Content-Encoding: br
Vary: Accept-Encoding
Content-Length: 34821

O cabeçalho Vary: Accept-Encoding instrui caches intermediários (CDN, proxy corporativo, service worker) a manter versões separadas por codificação. Omiti-lo é o erro clássico que faz um usuário sem suporte a Brotli receber bytes que não consegue decodificar.

Como habilitar Brotli no Nginx

O Nginx precisa do módulo ngx_brotli, mantido pelo Google e disponível como módulo dinâmico em Ubuntu 24.04+, Debian 12+ e Alpine 3.19+. A configuração canônica separa Brotli estático (pré-comprimido) de Brotli dinâmico (on-the-fly):

load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

http {
    # Serve .br pré-gerado se existir; economiza CPU
    brotli_static on;

    # Fallback: comprime dinamicamente em nível 5 (bom balanço)
    brotli on;
    brotli_comp_level 5;
    brotli_min_length 1024;
    brotli_types
        text/plain
        text/css
        text/xml
        application/javascript
        application/json
        application/xml+rss
        application/atom+xml
        image/svg+xml
        font/ttf
        font/eot;

    # Mantenha gzip como fallback para clientes sem Brotli
    gzip on;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_min_length 1024;
    gzip_types
        text/plain
        text/css
        application/javascript
        application/json
        image/svg+xml;
}

Pré-comprimir no build é essencial. Adicione ao pipeline (exemplo com Vite):

import { defineConfig } from 'vite';
import compression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [
    compression({ algorithm: 'brotliCompress', ext: '.br', threshold: 1024 }),
    compression({ algorithm: 'gzip', ext: '.gz', threshold: 1024 }),
  ],
});

Com brotli_static on, o Nginx encontra app.js.br ao lado de app.js e serve o arquivo pré-comprimido sem gastar CPU por request. Ideal para assets hasheados com cache imutável.

Zstandard em 2026: quando usar

Zstd chegou aos navegadores em fevereiro de 2024 (Chrome 123, Firefox 126, Safari 17.4) e, em 2026, cobre aproximadamente 88% do tráfego global. Honestamente, virou meu default para respostas dinâmicas: APIs JSON, HTML renderizado no servidor, streams de eventos. Ele combina ratio próximo ao Brotli com custo de CPU 3 a 4× menor. Facebook, Netflix e Cloudflare relatam economia de 4 a 8% de bandwidth ao migrar dinâmicos para Zstd.

Habilitar em Node.js com Fastify:

import fastify from 'fastify';
import compress from '@fastify/compress';
import zlib from 'node:zlib';

const app = fastify();

await app.register(compress, {
  encodings: ['zstd', 'br', 'gzip'], // ordem de preferência
  threshold: 1024,
  zlibOptions: { level: 6 },
  brotliOptions: { params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 5 } },
});

app.get('/api/products', async () => {
  return await db.products.findMany();
});

Cloudflare Workers habilitam Zstd automaticamente desde novembro de 2024 quando o cliente envia Accept-Encoding: zstd. Em Fastly, adicione ao VCL:

if (req.http.Accept-Encoding ~ "zstd") {
    set req.http.Accept-Encoding = "zstd";
} else if (req.http.Accept-Encoding ~ "br") {
    set req.http.Accept-Encoding = "br";
} else if (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
}

Compression Dictionary Transport: a grande virada

Compression Dictionary Transport (CDT) é a maior novidade em compressão web da década. Especificado pelo IETF em 2024 e disponível desde Chrome 123, permite que o servidor use uma versão anterior do mesmo recurso como dicionário para comprimir a nova versão. Em bundles JavaScript que mudam pouco entre deploys, o delta resultante pode ser 70 a 90% menor que a compressão Brotli tradicional.

O fluxo é:

  1. Servidor envia app-v42.js com Use-As-Dictionary: match="/assets/app-*.js".
  2. Navegador armazena o arquivo como dicionário reutilizável.
  3. Em uma navegação futura, requisita app-v43.js incluindo Available-Dictionary: :SHA256=....
  4. Servidor comprime v43 usando v42 como dicionário e responde com Content-Encoding: dcb (Brotli) ou dcz (Zstd).

Exemplo real: no lançamento do Chrome 127, o Google reportou que atualizações do bundle do Search News caíram de 45 KB (Brotli) para 3.8 KB (CDT + Zstd). Impressionante, né? Para configurar em Nginx com um script auxiliar:

location ~* ^/assets/app-.*\.js$ {
    add_header Use-As-Dictionary 'match="/assets/app-*.js", type="raw"';
    add_header Vary "Accept-Encoding, Available-Dictionary";
    expires 1y;
}

O servidor precisa manter os dicionários indexados por hash SHA-256 e executar Brotli/Zstd em modo shared dictionary. Ferramentas prontas em 2026: @cloudflare/compression-dictionary-transport (Workers), fastly-cdt (VCL), e o middleware oficial express-cdt para Node. Consulte a especificação IETF de Compression Dictionary Transport para detalhes de negociação.

Compressão em CDN: Cloudflare, Fastly e Cloudfront

CDNs modernas fazem compressão automática, só que com defaults distintos que afetam performance. Compreender essas diferenças evita retrabalho.

CDNBrotli automáticoZstd automáticoNível on-the-flyCDT (2026)
CloudflareSim (nível 4)Sim, desde 11/2024Brotli 4, Zstd 3Beta público
FastlySim, via VCLSim, desde 2025ConfigurávelPreview
AWS CloudFrontSim (nível 4)Ainda nãoFixo, não ajustávelAinda não
Bunny CDNSim (nível 6)Sim, desde 2025Brotli 6, Zstd 6Roadmap

Interações com cache HTTP de edge merecem atenção. Um CDN mal configurado pode cachear uma resposta comprimida em Brotli e servi-la a um cliente que só entende gzip, causando erro decoding failure. Já peguei esse bug em produção uma vez e passei três horas achando que era problema do servidor de origem. Sempre inclua Vary: Accept-Encoding ou use a normalização automática do CDN. Cloudflare, Fastly e Bunny já normalizam por padrão; CloudFront exige Compress objects automatically = Yes na behavior.

Origem comprimida vs recompressão no edge

Se o origin server já envia respostas Brotli-11 pré-comprimidas (assets estáticos), o CDN deve passar o corpo intacto, nunca recomprimir. Cloudflare respeita isso quando você define Cache-Control: immutable no origin. Recompressão intermediária é sempre pior: dobra o custo de CPU e, para Brotli, produz ratio ligeiramente inferior ao original.

Como medir e validar a compressão

Não confie na configuração. Meça. Três abordagens complementares:

1. curl para checagem rápida:

curl -sI -H "Accept-Encoding: zstd, br, gzip" https://example.com/assets/app.js \
  | grep -iE 'content-encoding|content-length|vary'

2. Lighthouse CI para regressão: a audit uses-text-compression falha se qualquer recurso de texto > 1400 bytes for servido sem compressão. Integre em GitHub Actions com lhci autorun --collect.settings.throttlingMethod=devtools.

3. WebPageTest para análise real: execute com localização, dispositivo e conexão representativos. Na aba "Compression", ele lista bytes economizados por recurso e sugere melhorias. O guia oficial do Chrome sobre uses-text-compression detalha os thresholds. Vale também dar uma olhada no codelab de Brotli do web.dev, com exemplos práticos passo a passo.

Um exemplo de script bash para auditar todo um site:

#!/usr/bin/env bash
URL=$1
curl -s "$URL" | grep -oE 'src="[^"]+\.(js|css)"' | cut -d'"' -f2 | while read asset; do
  full="${URL%/}${asset}"
  size_raw=$(curl -s -H "Accept-Encoding: identity" -o /dev/null -w '%{size_download}' "$full")
  size_br=$(curl -s -H "Accept-Encoding: br" -o /dev/null -w '%{size_download}' "$full")
  ratio=$(echo "scale=2; ($size_raw - $size_br) * 100 / $size_raw" | bc)
  printf "%-60s raw=%-8s br=%-8s savings=%s%%\n" "$asset" "$size_raw" "$size_br" "$ratio"
done

Erros comuns e footguns

Comprimir binários já comprimidos. WOFF2, WebP, AVIF, MP4, MP3, ZIP e JPEG têm compressão interna. Brotli neles reduz < 0.5% e queima CPU. Nunca inclua font/woff2, image/webp ou image/avif em brotli_types ou gzip_types.

BREACH e CRIME em HTTPS. Ataques históricos (2012–2013) exploravam compressão sobre HTTPS para vazar tokens CSRF. Mitigação em 2026: use HTTP/2 ou HTTP/3 (comprimem cabeçalhos com HPACK/QPACK que não vazam corpo), evite refletir input do usuário em respostas comprimidas junto com segredos, e adicione tokens CSRF fora de payloads comprimidos.

Cache-Control conflitante com Vary. Um CDN com Cache-Control: public, max-age=3600 mas sem Vary: Accept-Encoding pode servir respostas Brotli a clientes gzip-only. Sempre inclua Vary em recursos comprimidos dinamicamente. Para recursos estáticos com URL versionada, você pode omitir Vary se o CDN faz normalização.

Comprimir respostas pequenas. Abaixo de ~150 bytes, o overhead do header comprimido supera a economia. Configure *_min_length 1024 como default; para APIs muito chatas, 512 pode ser justificado.

Ignorar Save-Data. Usuários com Save-Data: on preferem respostas menores mesmo que exijam mais CPU no servidor. Considere usar Brotli-11 pré-comprimido em vez de gzip-6 dinâmico para essa audiência.

Perguntas Frequentes

Brotli é sempre melhor que gzip?

Para conteúdo estático pré-comprimido, sim: Brotli-11 entrega 15 a 25% a menos de bytes que gzip-9. Para compressão on-the-fly em respostas dinâmicas, Brotli-4 ou 5 vence gzip-6 em ratio mas com custo de CPU comparável. Manter gzip como fallback ainda é obrigatório para clientes legados.

Qual o melhor nível de compressão Brotli para produção?

Use nível 11 apenas para pré-compressão no build de assets estáticos. Para compressão dinâmica (por request), nível 4 ou 5 oferece a melhor relação custo/benefício; níveis 8+ dinâmicos são inviáveis pois demoram 200 a 800 ms por MB.

Zstd substitui Brotli em 2026?

Não. Zstd é superior para respostas dinâmicas por sua velocidade, mas Brotli-11 pré-comprimido ainda produz os menores arquivos absolutos para conteúdo estático. A estratégia recomendada é: Brotli-11 estático + Zstd dinâmico + gzip fallback.

O que é Compression Dictionary Transport?

É uma extensão do HTTP que permite usar uma versão anterior de um recurso como dicionário para comprimir a nova versão. Reduz o tamanho de atualizações de bundles em 70 a 90% comparado a compressão tradicional. Disponível desde Chrome 123 (março de 2024).

Preciso configurar Vary: Accept-Encoding manualmente?

Sim, sempre que servir respostas comprimidas dinamicamente através de caches intermediários. CDNs como Cloudflare e Fastly normalizam automaticamente, mas Nginx e Apache exigem configuração explícita. Sem Vary, você arrisca servir bytes Brotli a um cliente gzip-only.

Editorial Team
Sobre o Autor Editorial Team

Our team of expert writers and editors.