La documentación de Cloudflare Pages te dice que el límite son 2000 redirecciones. No miente, pero apunta al número equivocado. El límite que quitó redirecciones críticas de este sitio en producción fue el límite de tamaño de archivo de 100KB, y el modo de fallo es del peor tipo: silencioso. Sin error de build. Sin aviso de deploy. Sin línea de log. El archivo _redirects se sube, el deploy se pone en verde, y un bloque de tus reglas sencillamente no se aplica nunca.
Esto es una polémica con la forma en que se enseña el límite. “Mantente por debajo de 2000 reglas” es el consejo que todo el mundo repite, y es el consejo que dejó crecer nuestro archivo hasta unos 157KB mientras seguía muy lejos de las 2000 reglas. El número que importaba nunca estuvo en la frase que vigilábamos.
El límite de bytes del _redirects de Cloudflare: TL;DR en 4 puntos
- Cloudflare Pages limita el
_redirectsde tres maneras: 2000 reglas estáticas, 100 reglas dinámicas y 100KB de tamaño de archivo. La primera es la que todos citan; la tercera es la que rompe producción. - Las reglas más allá del corte de bytes de 100KB se descartan cuando el archivo se procesa en el deploy. No hay aviso. El archivo desplegado sencillamente deja de aplicar reglas a partir de cierta línea.
- Un sitio en seis idiomas con slugs descriptivos largos cruza los 100KB en torno a las 1200 a 1300 reglas, muy por debajo del límite de número de reglas. Así que chocas contra la pared de bytes mientras el panel aún dice que tienes margen.
- El arreglo no es “borrar redirecciones”. Es mover las reglas uno-a-uno en masa a una Pages Function, que está limitada por un tamaño de script comprimido de 1MB, no por el límite de 100KB del redirects.
Glosario: _redirects, Pages Functions, splat, 301
Este caso descansa sobre unos pocos conceptos de la plataforma. Si alguno te resulta desconocido, vale treinta segundos, porque el fallo se esconde justo en el hueco entre ellos.
_redirects- un archivo de texto plano en la salida del build (aquípublic/_redirects) en el que cada línea es una regla: una ruta de origen, un destino y un código de estado opcional. Cloudflare Pages lo lee en el deploy y aplica las reglas en el edge antes de que tu sitio reciba la petición.- Redirección estática - una regla literal uno-a-uno, por ejemplo
/old-page/ /new-page/ 301. Sin comodines. - Redirección dinámica - una regla con un comodín
*o un placeholder:splat, por ejemplo/blog/* /articles/:splat 301. Estas usan el motor de plantillas de ruta de Cloudflare y están limitadas a 100 por archivo. - 301 - el estado HTTP de una redirección permanente. Le dice a Google que la URL antigua se ha movido para siempre y que la señal de ranking debe seguir hacia la nueva URL.
- Pages Function - un pequeño script serverless (aquí en
functions/) que se ejecuta en el edge en cada petición que coincide. Puede leer una tabla de consulta y emitir redirecciones en código, sin techo de 100KB. _middleware.ts- la Pages Function que se ejecuta en cada petición antes del routing. El lugar natural para hacer una consulta al mapa y emitir un 301 si la ruta coincide.
Estas distinciones son invisibles hasta que una redirección deja de disparar. Entonces son toda la historia.
Cómo un archivo _redirects de 157KB rompió producción
El archivo no creció de forma temeraria. Creció como crece el mapa de redirecciones de cualquier sitio multilingüe de larga vida: cada vez que se limpiaba un slug, se retiraba una URL obsoleta o se reorganizaba una variante de idioma, se añadía un par (viejo, nuevo). Seis idiomas, slugs descriptivos como /pl/tworzenie-stron-internetowych-oraz-sklepow-wordpress/ y unos años de mantenimiento pusieron el archivo en torno a 157KB y unas 1890 reglas.
Nadie estaba preocupado, porque 1890 está por debajo de 2000. Ese fue el error. El límite de bytes se había cruzado mucho antes de que el límite de reglas estuviera ni cerca.
El síntoma, al principio, no parecía un problema de redirecciones. Parecían tres incendios sin relación:
- Google Merchant Center marcó dos de doce productos como páginas de producto no disponibles. Los destinos de su feed eran redirecciones que quedaban cerca del final del archivo.
- Google Search Console reportó 388 URL con “No encontrada (404)”. Una gran parte de ellas tenía entradas en
_redirectsque, sobre el papel, deberían haberlas capturado. - La validación en GSC seguía fallando una y otra vez. Pedíamos la validación, Google volvía a la URL, chocaba con el mismo 404 porque la redirección nunca estuvo activa, y rechazaba la validación. El bucle no se rompía solo.
Las páginas, las plantillas, el build, el número de reglas, todo parecía sano. La capa de routing había sido amputada en silencio por debajo de una línea que nadie miraba.
Cómo confirmar que la cola se está descartando
El diagnóstico es mecánico en cuanto dejas de confiar en el archivo y empiezas a confiar en el edge. No muestrees reglas al azar; muéstrealas por posición.
- Toma una regla cerca del principio del
_redirects, una del centro y una cerca del final. - Solicita cada ruta de origen en producción y lee solo el código de estado:
curl -s -o /dev/null -w "%{http_code}" https://tu-sitio/ruta-de-origen/. - Compara. En este sitio, las reglas en torno a la línea 9 a 130 devolvían
301de forma limpia. Las reglas más allá de la línea 200 aproximadamente devolvían404, con algunos pases falsos en los que lógica de middleware sin relación (detección de slugs entre idiomas, patrones heredados) capturaba la URL por otro camino por casualidad.
Cuando el principio del archivo funciona y la cola da 404 mientras ambas reglas están confirmadas e idénticas en forma, la conclusión no es ambigua: el archivo se está truncando en el límite de bytes. La línea de corte exacta depende de cuán larga sea tu regla media, y por eso un sitio en seis idiomas con slugs largos choca con él antes de lo que sugiere el número de reglas.
Por qué el límite de bytes es el límite vinculante, no el número de reglas
| Límite | Valor documentado | Qué cuenta | Cuándo muerde |
|---|---|---|---|
| Redirecciones estáticas | 2000 reglas | Líneas literales uno-a-uno | Sitios grandes, con el tiempo |
| Redirecciones dinámicas | 100 reglas | Líneas con * o :splat | Uso intenso de comodines |
| Tamaño de archivo | 100KB | Bytes totales del archivo | URL largas en muchos idiomas, pronto |
La aritmética es todo el argumento. Una regla corta como /a/ /b/ 301 ocupa unos 12 bytes. Una regla multilingüe realista, /pl/tworzenie-stron-wordpress/ /pl/tworzenie-stron-internetowych-oraz-sklepow-wordpress/ 301, se acerca más a los 90 bytes. A 80 o 90 bytes por regla, los 100KB se agotan en torno a las 1200 a 1300 reglas - cientos por debajo de las 2000 que la documentación pone en primer plano. El límite que vigilas debería ser el que alcanzas primero, y para sitios de slugs descriptivos ese límite es en bytes, no en líneas.
Qué dice la documentación de Cloudflare, y qué deja fuera
La documentación de redirecciones sí enumera los tres límites. La cifra de 100KB está ahí por escrito. Lo que la página no dice, en ninguna parte, es qué pasa cuando lo superas: las reglas más allá del corte se descartan, y el deploy tiene éxito de todos modos. El contraste con el límite de número de reglas importa. Supera 2000 reglas y el build lo saca a la luz; el archivo es demasiado grande de una manera de la que la plataforma te avisa. Supera 100KB y la plataforma trunca y se queda callada.
Esa asimetría es la trampa. Un límite que falla en voz alta te entrena a respetarlo. Un límite que falla en silencio te entrena a ignorarlo, porque nada se pone nunca en rojo. La misma clase de problema aparece en el archivo hermano _headers, que lleva sus propias restricciones de tamaño, y en cualquier artefacto de build donde “hizo deploy” se confunde con “se aplicó todo”. El contrato de plataforma que deberías interiorizar no es el número más grande de la página de límites; es el número más pequeño que falla sin avisarte. El mismo hueco de confianza está en la base de nuestro artículo anterior sobre cómo la traducción por IA rompe el SEO multilingüe en la capa estructural: en ambos casos la salida visible parece correcta mientras la capa de routing por debajo está rota.
El arreglo: mover las redirecciones en masa a una Pages Function
El _redirects es el almacenamiento equivocado para miles de reglas literales. El almacenamiento correcto es una Pages Function que lee un mapa. Las Functions están limitadas por el tamaño del script comprimido, hasta 1MB, no por el límite de 100KB del redirects, así que un mapa de redirecciones de 200KB cabe con unas cinco veces el margen.
La migración en este sitio, entregada en un único commit el 2026-05-07, tuvo tres partes:
functions/redirect-map.tsexporta unReadonlyMap<string, string>de pares origen-destino. Las claves se normalizan una vez - en minúsculas, con barra final añadida, barras repetidas colapsadas - de modo que cada petición es una única consulta O(1), no un escaneo. Empezó con 1851 entradas y ahora tiene 2233.functions/_middleware.tsrealiza la consulta entre los pasos de normalización existentes (colapso de barras, asciificación de diacríticos) y el paso de la barra final. Construye la clave normalizada, comprueba el mapa y emite un 301 directo al destino cuando acierta.- El
public/_redirectsse recortó de unos 157KB a grosso modo 3,3KB y 41 reglas: un comentario de cabecera, cuatro reglas del Merchant Center de máxima prioridad, y las reglas con comodín o:splatque de verdad necesitan el motor de plantillas de ruta de Cloudflare.
Treinta reglas muestreadas al azar del nuevo mapa devolvieron todas 301 de forma limpia en producción. El bucle de 404 en Search Console terminó en cuanto las redirecciones que seguía esperando existieron de verdad en el edge.
El orden del middleware es parte del arreglo
Mover las reglas a una Function solo es correcto si la consulta se ejecuta en el punto adecuado de la petición. El _middleware.ts ya hacía trabajo real antes de la migración: pasa a minúsculas y colapsa barras repetidas, asciifica diacríticos para que /pl/wdrozenia/ y una variante cargada de diacríticos resuelvan a la misma ruta, y añade una barra final. La consulta al mapa tiene que ir después de la normalización y antes de la redirección de barra final, o aparecen dos bugs.
Pon la consulta demasiado pronto, antes de que se colapsen las barras, y una clave que se normalizó en tiempo de build (minúsculas, barras únicas, barra final) nunca coincide con una ruta de entrada en crudo con doble barra o mayúsculas y minúsculas mezcladas. El mapa falla en silencio y la URL cae a un 404, que parece exactamente el bug que intentabas arreglar. Ponla demasiado tarde, después de que la redirección de barra final ya haya emitido un 301, y pagas dos saltos por cada petición redirigida: uno para añadir la barra, otro para llegar al destino. Las redirecciones de dos saltos sangran link equity y ralentizan el rastreo. El mapa debe consumir la clave ya normalizada y hacer cortocircuito con un único 301. La lógica de routing en el edge es secuencial, no un saco de reglas independientes, y el orden es tan estructural como las propias reglas. Hay más artículos sobre edge y plataformas en el blog de wppoland.
Alternativas que rechazamos, y por qué
Un mapa estático compilado dentro de la Function no era la única opción. Había otras dos sobre la mesa.
- Workers KV. Guardar los pares de redirección en un namespace clave-valor y consultarlos en tiempo de ejecución. Esto escala a millones de entradas y desacopla las redirecciones de los deploys. Lo rechazamos para este sitio: una lectura de KV añade latencia de red a cada petición que pueda ser una redirección, los límites de lectura del plan gratuito son un techo real con nuestro tráfico, y 2200 reglas caben cómodamente en un mapa compilado que viaja con la Function y no cuesta nada en tiempo de petición. KV se gana su sitio cuando el conjunto de redirecciones es lo bastante grande o volátil como para que volver a hacer deploy para cambiarlo resulte doloroso. El nuestro no es ni lo uno ni lo otro.
- Dividir el
_redirectsen varios archivos más pequeños. Cloudflare Pages lee un único archivo_redirects; no hay mecanismo de include, así que esto nunca fue real. El instinto detrás de ello - seguir usando la función nativa de la plataforma - es el mismo instinto que dejó crecer el archivo más allá del límite, para empezar.
El mapa compilado ganó porque retira el límite de la ecuación por completo mientras mantiene las consultas en memoria y a coste cero por petición. La decisión no es universal; es la correcta para un conjunto de redirecciones del orden de los pocos miles que cambia unas pocas veces al mes.
Cómo mantener la capa de redirecciones sana después
La migración no es una huida única; sin disciplina, el archivo vuelve a crecer. Las reglas que se han mantenido desde entonces:
- Las nuevas redirecciones estáticas uno-a-uno van al mapa de la Function, nunca al
_redirects. Añade afunctions/redirect-map.ts. - Las nuevas redirecciones con comodín o
:splatvan al_redirects, que ahora tiene grosso modo treinta veces su margen anterior bajo el límite. - Vigila el tamaño en bytes, no el número de reglas. Una línea en CI que haga fallar el build si
public/_redirectscruza los 50KB aproximadamente da un margen amplio antes de la pared silenciosa de los 100KB. El número de reglas es aquí una métrica de vanidad; los bytes son el contrato. - Comprueba por posición después de cualquier cambio grande de redirecciones. Principio, centro, cola. Cuesta tres llamadas
curly atrapa el truncamiento antes que Google.
La lección más profunda sobrevive a Cloudflare en concreto. Un límite de plataforma que falla en silencio es más peligroso que un límite duro que da error, porque el deploy en verde te entrena a confiar en un archivo que ya no se aplica por completo. Cuando un límite se documenta como un número y se impone como otro, el hueco es el lugar donde se rompe producción. Lee la página de límites por cada número que haya en ella, luego verifica el que falla en silencio contra el edge en vivo, no contra el archivo confirmado.



