A documentação da Cloudflare Pages diz-lhe que o limite são 2000 redirects. Não está a mentir, mas está a apontar para o número errado. O limite que retirou redirects críticos deste site em produção foi o limite de tamanho de ficheiro de 100KB, e o modo de falha é do pior tipo: silencioso. Sem erro de build. Sem aviso de deploy. Sem linha de log. O ficheiro _redirects carrega, o deploy fica verde, e um conjunto das suas regras simplesmente nunca se aplica.
Esta é uma polémica com a forma como o limite é ensinado. “Fique abaixo das 2000 regras” é o conselho que toda a gente repete, e é o conselho que deixou o nosso ficheiro crescer até cerca de 157KB enquanto ainda estava longe das 2000 regras. O número que importava nunca esteve na frase que andávamos a vigiar.
O limite de bytes do _redirects da Cloudflare: TL;DR em 4 pontos
- A Cloudflare Pages limita o
_redirectsde três formas: 2000 regras estáticas, 100 regras dinâmicas e 100KB de tamanho de ficheiro. A primeira é a que toda a gente cita; a terceira é a que parte a produção. - As regras para lá do corte de bytes de 100KB são descartadas quando o ficheiro é processado no deploy. Não há aviso. O ficheiro implantado simplesmente deixa de aplicar regras a partir de certa linha.
- Um site em seis idiomas com slugs descritivos longos ultrapassa os 100KB por volta das 1200 a 1300 regras, muito abaixo do limite de contagem de regras. Por isso bate na parede de bytes enquanto o painel ainda diz que tem folga.
- A correção não é “apagar redirects”. É mover as regras um-para-um em massa para uma Pages Function, que está limitada por um tamanho de script comprimido de 1MB, não pelo limite de 100KB do redirects.
Glossário: _redirects, Pages Functions, splat, 301
Este caso assenta em alguns conceitos da plataforma. Se algum lhe for desconhecido, vale trinta segundos, porque a falha esconde-se exatamente na lacuna entre eles.
_redirects- um ficheiro de texto simples na saída do build (aquipublic/_redirects) em que cada linha é uma regra: um caminho de origem, um destino e um código de estado opcional. A Cloudflare Pages lê-o no deploy e aplica as regras no edge antes de o seu site ser atingido.- Redirect estático - uma regra literal um-para-um, por exemplo
/old-page/ /new-page/ 301. Sem wildcards. - Redirect dinâmico - uma regra com um wildcard
*ou um placeholder:splat, por exemplo/blog/* /articles/:splat 301. Estas usam o motor de templates de caminho da Cloudflare e estão limitadas a 100 por ficheiro. - 301 - o estado HTTP de um redirect permanente. Diz à Google que o URL antigo mudou definitivamente e que o sinal de ranking deve seguir para o novo URL.
- Pages Function - um pequeno script serverless (aqui em
functions/) que corre no edge em cada pedido correspondente. Pode ler uma tabela de consulta e emitir redirects em código, sem teto de 100KB. _middleware.ts- a Pages Function que corre em cada pedido antes do routing. O lugar natural para fazer uma consulta ao mapa e emitir um 301 se o caminho corresponder.
Estas distinções são invisíveis até um redirect deixar de disparar. Aí, são toda a história.
Como um ficheiro _redirects de 157KB partiu a produção
O ficheiro não cresceu de forma imprudente. Cresceu da forma como cresce o mapa de redirects de qualquer site multilingue de vida longa: sempre que um slug era limpo, um URL obsoleto reformado ou uma variante de idioma reorganizada, anexava-se um par (antigo, novo). Seis idiomas, slugs descritivos como /pl/tworzenie-stron-internetowych-oraz-sklepow-wordpress/ e alguns anos de arrumação puseram o ficheiro em cerca de 157KB e cerca de 1890 regras.
Ninguém estava preocupado, porque 1890 está abaixo de 2000. Foi esse o erro. O limite de bytes tinha sido ultrapassado muito antes de o limite de regras estar sequer perto.
O sintoma, ao início, não parecia um problema de redirects. Parecia três incêndios sem relação entre si:
- O Google Merchant Center sinalizou dois de doze produtos como páginas de produto indisponíveis. Os destinos do feed deles eram redirects que ficavam perto do fundo do ficheiro.
- A Google Search Console reportou 388 URLs “Não encontrado (404)”. Uma grande parte deles tinha entradas no
_redirectsque, no papel, deveriam tê-los apanhado. - A validação na GSC continuava a falhar repetidamente. Pedíamos a validação, a Google revisitava o URL, batia no mesmo 404 porque o redirect nunca esteve ativo, e rejeitava a validação. O ciclo não se quebrava sozinho.
As páginas, os templates, o build, a contagem de regras, tudo parecia saudável. A camada de routing tinha sido amputada em silêncio abaixo de uma linha para a qual ninguém olhava.
Como confirmar que a cauda está a ser descartada
O diagnóstico é mecânico assim que deixar de confiar no ficheiro e começar a confiar no edge. Não amostre regras ao acaso; amostre-as por posição.
- Pegue numa regra perto do topo do
_redirects, uma do meio e uma perto do fundo. - Peça cada caminho de origem em produção e leia apenas o código de estado:
curl -s -o /dev/null -w "%{http_code}" https://o-seu-site/caminho-de-origem/. - Compare. Neste site, as regras por volta da linha 9 a 130 devolviam
301de forma limpa. As regras para lá de cerca da linha 200 devolviam404, com algumas passagens falsas em que lógica de middleware sem relação (deteção de slugs entre idiomas, padrões legados) apanhava o URL por outro caminho por acaso.
Quando o topo do ficheiro funciona e a cauda dá 404 enquanto ambas as regras estão confirmadas e idênticas na forma, a conclusão não é ambígua: o ficheiro está a ser truncado no limite de bytes. A linha exata de corte depende do comprimento médio da sua regra, e é por isso que um site em seis idiomas com slugs longos bate nela mais cedo do que a contagem de regras sugere.
Porque o limite de bytes é o limite vinculativo, não a contagem de regras
| Limite | Valor documentado | O que conta | Quando morde |
|---|---|---|---|
| Redirects estáticos | 2000 regras | Linhas literais um-para-um | Sites grandes, eventualmente |
| Redirects dinâmicos | 100 regras | Linhas com * ou :splat | Uso intenso de wildcards |
| Tamanho do ficheiro | 100KB | Total de bytes do ficheiro | URLs longos em muitos idiomas, cedo |
A aritmética é todo o argumento. Uma regra curta como /a/ /b/ 301 tem cerca de 12 bytes. Uma regra multilingue realista, /pl/tworzenie-stron-wordpress/ /pl/tworzenie-stron-internetowych-oraz-sklepow-wordpress/ 301, fica mais perto dos 90 bytes. A 80 ou 90 bytes por regra, os 100KB esgotam-se por volta das 1200 a 1300 regras - centenas abaixo das 2000 que a documentação põe em primeiro plano. O limite que deve vigiar deve ser aquele em que bate primeiro, e para sites de slugs descritivos esse limite é em bytes, não em linhas.
O que a documentação da Cloudflare diz, e o que deixa de fora
A documentação de redirects lista de facto os três limites. O valor de 100KB está lá por escrito. O que a página não diz, em lado nenhum, é o que acontece quando o ultrapassa: as regras para lá do corte são descartadas, e o deploy tem sucesso na mesma. O contraste com o limite de contagem de regras importa. Ultrapasse 2000 regras e o build trá-lo à superfície; o ficheiro está grande demais de uma forma de que a plataforma o avisa. Ultrapasse 100KB e a plataforma trunca e fica calada.
Essa assimetria é a armadilha. Um limite que falha em voz alta treina-o a respeitá-lo. Um limite que falha em silêncio treina-o a ignorá-lo, porque nada fica nunca a vermelho. A mesma classe de problema surge no ficheiro irmão _headers, que carrega as suas próprias restrições de tamanho, e em qualquer artefacto de build em que “fez deploy” se confunde com “aplicou-se tudo”. O contrato de plataforma que deve interiorizar não é o maior número na página de limites; é o menor número que falha sem lhe dizer. A mesma lacuna de confiança está na base do nosso artigo anterior sobre como a tradução por IA parte o SEO multilingue na camada estrutural: em ambos os casos a saída visível parece correta enquanto a camada de routing por baixo está partida.
A correção: mover os redirects em massa para uma Pages Function
O _redirects é o armazenamento errado para milhares de regras literais. O armazenamento certo é uma Pages Function que lê um mapa. As Functions estão limitadas pelo tamanho do script comprimido, até 1MB, não pelo limite de 100KB do redirects, pelo que um mapa de redirects de 200KB cabe com cerca de cinco vezes a folga.
A migração neste site, entregue num único commit a 2026-05-07, teve três partes:
functions/redirect-map.tsexporta umReadonlyMap<string, string>de pares origem-destino. As chaves são normalizadas uma vez - em minúsculas, com barra final adicionada, barras repetidas colapsadas - de modo que cada pedido é uma única consulta O(1), não uma varredura. Começou com 1851 entradas e tem agora 2233.functions/_middleware.tsfaz a consulta entre os passos de normalização existentes (colapso de barras, asciificação de diacríticos) e o passo da barra final. Constrói a chave normalizada, verifica o mapa e emite um 301 direto para o alvo quando acerta.- O
public/_redirectsfoi reduzido de cerca de 157KB para grosso modo 3,3KB e 41 regras: um comentário de cabeçalho, quatro regras do Merchant Center de prioridade máxima, e as regras com wildcard ou:splatque precisam mesmo do motor de templates de caminho da Cloudflare.
Trinta regras amostradas ao acaso do novo mapa devolveram todas 301 de forma limpa em produção. O ciclo de 404 na Search Console terminou assim que os redirects que ela continuava a esperar passaram a existir de facto no edge.
A ordem do middleware faz parte da correção
Mover as regras para uma Function só é correto se a consulta correr no ponto certo do pedido. O _middleware.ts já fazia trabalho real antes da migração: põe em minúsculas e colapsa barras repetidas, asciifica diacríticos para que /pl/wdrozenia/ e uma variante carregada de diacríticos resolvam para a mesma rota, e adiciona uma barra final. A consulta ao mapa tem de ficar depois da normalização e antes do redirect da barra final, ou aparecem dois bugs.
Ponha a consulta cedo demais, antes de as barras serem colapsadas, e uma chave que foi normalizada em tempo de build (minúsculas, barras únicas, barra final) nunca corresponde a um caminho de entrada em bruto com barra dupla ou maiúsculas e minúsculas misturadas. O mapa falha em silêncio e o URL cai para um 404, que parece exatamente o bug que estava a tentar corrigir. Ponha-a tarde demais, depois de o redirect da barra final já ter emitido um 301, e paga dois saltos por cada pedido redirecionado: um para adicionar a barra, outro para chegar ao destino. Os redirects de dois saltos sangram link equity e abrandam o crawl. O mapa tem de consumir a chave já normalizada e fazer curto-circuito com um único 301. A lógica de routing no edge é sequencial, não um saco de regras independentes, e a ordem é tão estruturante quanto as próprias regras. Mais artigos sobre edge e plataformas estão no blog wppoland.
Alternativas que rejeitámos, e porquê
Um mapa estático compilado para dentro da Function não era a única opção. Havia outras duas em cima da mesa.
- Workers KV. Guardar os pares de redirect num namespace chave-valor e consultá-los em tempo de execução. Isto escala para milhões de entradas e desacopla os redirects dos deploys. Rejeitámo-lo para este site: uma leitura de KV adiciona latência de rede a cada pedido que possa ser um redirect, os limites de leitura do plano gratuito são um teto real no nosso tráfego, e 2200 regras cabem confortavelmente num mapa compilado que viaja com a Function e não custa nada em tempo de pedido. O KV ganha o seu lugar quando o conjunto de redirects é grande ou volátil o suficiente para que voltar a fazer deploy para o alterar seja doloroso. O nosso não é nem uma coisa nem outra.
- Dividir o
_redirectspor vários ficheiros mais pequenos. A Cloudflare Pages lê um único ficheiro_redirects; não há mecanismo de include, por isso isto nunca foi real. O instinto por trás disto - continuar a usar a funcionalidade nativa da plataforma - é o mesmo instinto que deixou o ficheiro crescer para lá do limite, para começar.
O mapa compilado venceu porque retira o limite da equação por completo enquanto mantém as consultas em memória e a custo zero por pedido. A decisão não é universal; é a certa para um conjunto de redirects na ordem dos baixos milhares que muda algumas vezes por mês.
Como manter a camada de redirects saudável depois
A migração não é uma fuga única; sem disciplina, o ficheiro volta a crescer. As regras que se mantiveram desde então:
- Os novos redirects estáticos um-para-um vão para o mapa da Function, nunca para o
_redirects. Acrescente aofunctions/redirect-map.ts. - Os novos redirects com wildcard ou
:splatvão para o_redirects, que tem agora grosso modo trinta vezes a folga anterior abaixo do limite. - Vigie o tamanho em bytes, não a contagem de regras. Uma linha em CI que faz o build falhar se o
public/_redirectspassar dos cerca de 50KB dá uma margem ampla antes da parede silenciosa dos 100KB. A contagem de regras é aqui uma métrica de vaidade; os bytes são o contrato. - Verifique por posição depois de qualquer alteração grande de redirects. Topo, meio, cauda. Leva três chamadas
curle apanha a truncagem antes da Google.
A lição mais profunda sobrevive à Cloudflare em concreto. Um limite de plataforma que falha em silêncio é mais perigoso do que um limite rígido que dá erro, porque o deploy verde treina-o a confiar num ficheiro que já não é aplicado por inteiro. Quando um limite é documentado como um número e imposto como outro, a lacuna é o sítio onde a produção parte. Leia a página de limites para cada número que lá esteja, depois verifique aquele que falha em silêncio contra o edge ao vivo, não contra o ficheiro confirmado.


