Los límites de Cloudflare Workers que deciden tu build
webdevelopment 23 de octubre de 2026 · Mintec

Los límites de Cloudflare Workers que deciden tu build

Cloudflare Workers frena deploys por tres razones fuera de tu código: 100.000 archivos por versión, un heap de Node mal dimensionado y nodejs_compat.

Cloudflare Workers rechaza un deploy por tres razones ajenas a que tu código esté mal: tu versión contiene más de 100.000 archivos estáticos, tu build se pasa del heap que Node realmente le dio, o tu ruta de peticiones depende en silencio de APIs de Node.js que se importan sin problema y fallan la primera vez que un usuario real entra a la ruta. Los dos primeros ya nos pasaron en sitios que mantenemos: un tope de archivos terminó una etapa de hosting, y un heap sin dimensionar detuvo un build a media renderización. Por eso cada techo de abajo ahora trae un chequeo que corremos antes del deploy y no después.

Esa es la idea de este artículo. Un límite que aprendes de un deploy fallido es un límite que pagaste dos veces: una en el push varado, otra en la carrera contra reloj. Los tres techos se ven venir si mides lo correcto, y ninguno necesita que la plataforma te avise primero.

Lo que la cobertura de "qué cambió" deja fuera

Ya cubrimos este clúster antes: el marco de decisión para el salto de Pages a Workers, la activación de Node.js en todo Worker, Astro vs Next.js con benchmarks reales y lo que el salto nos costó de verdad, medido. Todo eso responde qué cambió y cuánto cuesta. Nada responde la pregunta que un responsable técnico zanja antes del siguiente empujón de contenido: ¿qué se va a negar a hacer esta plataforma, y cuándo me voy a enterar? Sobra cobertura de límites en abstracto; casi no hay de tus límites — los que tu ritmo de crecimiento va a cruzar — porque exige que alguien describa el guarda en vez de parafrasear documentación.

Los tres techos, y qué prohíbe cada uno

Cada fila es una decisión que tomas ahora o la tomas durante un incidente. Las columnas del medio son las que la mayoría se salta.

TechoQué prohíbeQué te lleva hasta ahíEl guarda que conviene construirQué se rompe primero
100.000 archivos estáticos por versión de Worker (20.000 en Free)Publicar una versión con más archivos, sin importar cuán pequeño sea cada unoPáginas programáticas: cada nuevo servicio multiplicado por cada ciudad y cada idioma, así que el conteo se compone en cada releaseUn paso de build que cuenta el output y frena el deploy muy por debajo del topeEl deploy mismo — y luego cada push posterior, hasta que alguien borre páginas
Memoria de build — Cloudflare publica 8 GB para el contenedor, nada para tu heap de NodeUn build que se pasa del heap que Node realmente le dioNode deriva su heap por defecto de la máquina que encuentra — a menudo unos 2 GB — no de los 8 GB publicados del contenedorUn tope de heap explícito en el script de build, dimensionado al contenedor y no al laptopEl build muere a media renderización sin artefacto; producción sigue sirviendo la versión vieja
nodejs_compat activado por defecto (fechas de compatibilidad ≥ 2026-08-04)La suposición de que tu Worker no usa APIs de Node en absolutoCualquier dependencia npm que importe node:fs, node:path o node:crypto en la ruta de peticionesUna fecha de compatibilidad que elegiste y revisaste, más auditoría de dependencias antes de agregar unaUn módulo con polyfill se importa sin problema y luego falla cuando se llama a un método de verdad

Techo 1: el tope de archivos es una decisión de estrategia de contenido disfrazada de infraestructura

La página de límites de Cloudflare (actualizada el 12 de octubre de 2026) lista 20.000 archivos estáticos por versión de Worker en Free y 100.000 en Paid, con un techo de 25 MiB por archivo. Léela como una fila de infraestructura y la archivas. Léela como una restricción de arquitectura y cambia lo que construyes, porque el tope cuenta archivos, no bytes: una página de 40 KB y un video de 4 MB pesan lo mismo.

En un sitio programático, ese es todo el juego. Cuando las páginas se generan por ciudad × servicio × idioma, el conteo se compone: cada nuevo servicio se genera al instante para cada ciudad. Eso significa que el tope llega en un calendario que tú mismo fijas — es función de tu cadencia de contenido, no de tu tráfico. Y por eso puedes modelarlo antes de que duela: cuenta el output compilado en cada release, registra el delta por release y divide el margen restante entre ese delta. Si la respuesta cae dentro de tu horizonte de planificación, la decisión es de modelo de contenido — páginas hub, consolidación, servir la cola larga desde el Worker — y sale mucho más barata mientras sigue siendo una línea en un documento.

El guarda en sí es pequeño. Recorre el output compilado, cuenta cada archivo excepto los artefactos de enrutamiento y deja que el número decida si el deploy avanza:

const LIMIT = 100_000;        // el tope por versión de la plataforma
const WARN_AT = 0.8 * LIMIT;  // abre la conversación de modelo de contenido
const FAIL_AT = 0.99 * LIMIT; // frena el deploy antes de que ocurra

Por debajo de la línea de aviso solo imprime el conteo. Entre las dos, avisa. Arriba de la segunda, sale con código distinto de cero — y si el pipeline de deploy corre ese chequeo como parte de su comando de build, un deploy que cruzaría el tope no puede ocurrir por accidente. Ese último detalle es la diferencia entre un chequeo que recuerdas correr y un guarda que se corre solo.

La asimetría es lo que hace esto arquitectónico: un build fallido no te baja el sitio. Producción sigue sirviendo la versión anterior mientras cada push posterior falla hasta que alguien libere archivos. Tus visitantes no notan nada; tu pipeline está muerto. Es un fallo peor que una caída, porque una caída tiene prioridad.

Techo 2: el número de memoria que mató nuestros builds no aparece en ninguna página

Esta fila sorprende porque hay tres números de memoria en juego, y el que mata builds no estaba en ninguno. Cloudflare publica dos: la página de límites de ejecución documenta 128 MB por aislado y un tamaño máximo de Worker de 64 MiB, y la página de Workers Builds publica 8 GB de memoria por build (2 vCPU en Free, 4 en Paid) con un tiempo máximo de 20 minutos. El tercer número es el heap que realmente recibirá el proceso de tu framework, y ese no lo publica nadie — el V8 de Node lo deriva de la máquina que encuentra, así que el mismo build recibe un presupuesto distinto en tu laptop que dentro del contenedor. Estás compilando un sitio de decenas de miles de archivos contra un techo que no aparece en ningún panel.

El nuestro nos mostró la diferencia a la mala, y la secuencia enseña más que el resultado. El heap por defecto era cómodo en la máquina donde desarrollábamos y no alcanzaba dentro del contenedor de build. El push pasó, el build murió a media renderización y producción siguió sirviendo la versión anterior en silencio — que es el modo de fallo más caro, porque nada parece roto. El primer arreglo fue subir el número, y ese fue el instinto equivocado: un valor heredado de otra máquina es una preferencia, no una medición. El arreglo que aguantó fue tratar al contenedor como el presupuesto y dimensionar el techo a él, una sola vez y a propósito, en el script de build.

De esto salen dos reglas. Dimensiona el heap al contenedor, no al laptop. Y trata la cifra publicada del contenedor como suelo, no como el presupuesto de tu heap — la plataforma nunca te avisará de que lo que está por fallar es el reclamo por defecto de tu framework.

Techo 3: ya elegiste Node.js, quieras o no

Desde la fecha de compatibilidad 2026-08-04, Cloudflare activa nodejs_compat y nodejs_compat_v2 por defecto. Puedes desactivarlo con no_nodejs_compat y no_nodejs_compat_v2, pero lo importante es el defecto: cualquier Worker creado o migrado recién corre con la superficie de APIs de Node encendida.

Este es el techo que la gente falla en silencio, porque no parece un límite. La documentación de Cloudflare describe la trampa en una frase: además de las APIs con soporte nativo, Wrangler agrega "implementaciones shim de polyfill que te permiten importar el módulo, pero llamar a sus métodos lanza errores". El grafo de importaciones sigue verde. El build pasa. Entonces un visitante entra a una ruta que llama fs.readFile() y recibe un error que nadie vio en staging. La misma página lista APIs con soporte parcial — console, dns, module, os, perf_hooks, test, tls — donde "se importó" no es evidencia de que "funciona".

La postura que funciona es deliberada y no accidental. Sabe qué fecha de compatibilidad corre tu Worker de verdad, decide si la superficie de Node debe estar encendida y trata cada dependencia que busca un módulo de Node como un evento de revisión y no como un comportamiento por defecto. Escribimos qué cambia bajo ese comportamiento por defecto, incluida la trampa de process.env con Wrangler viejo.

Corre los mismos tres chequeos

Nada de esto requiere accesos especiales. Los chequeos son tres comandos y un hábito:

  1. Cuenta tus archivos compilados, no tus fuentes. find dist -type f | wc -l en cada build de producción, con fecha. Si la trayectoria entra en la zona de aviso dentro de tu horizonte de planificación, la decisión es de modelo de contenido, y es más barata antes del tope que después.
  2. Fija el heap de forma explícita y no confíes en el defecto. NODE_OPTIONS=--max-old-space-size=<presupuesto de tu contenedor> en el script de build, para que CI y laptops coincidan. Si tu plataforma no publica el presupuesto, súbelo hasta que los builds dejen de morir y luego bájalo hasta que casi lo hagan — ese recorrido es la medición.
  3. Lee tu fecha de compatibilidad y audita lo que importan tus dependencias. grep -r "node:" src/ functions/ worker/ antes de agregar una dependencia, no después de que una ruta falle. Si mantienes el defecto de Node — la mayoría lo hará — sabe qué APIs son nativas y cuáles son shims que fallan al llamarlas.

La decisión que hay que tomar antes de que el deploy la tome por ti

Un sitio estático en Workers apuesta a que el volumen de contenido se compone a tu favor. Y se compone — esa es la gracia de las páginas programáticas — y ese mismo crecimiento es lo que te acerca al tope de archivos. Elige el momento en que cruzas cada techo mientras todavía sea una línea del plan, o elígelo a las 2 a.m. con el pipeline detenido. La plataforma va a seguir sirviendo tu última versión buena en ambos casos, y por eso el aviso tiene que venir de tu propio pipeline.

Si estás dimensionando un salto de plataforma — o ya chocaste con una de estas filas — eso es el trabajo que hacemos en arquitectura web. Inicia un proyecto y trae tu conteo de archivos.

Preguntas Frecuentes

¿El límite de archivos de Workers cuenta cada página que genera mi framework?

Sí. Cada archivo que Wrangler sube como recurso estático cuenta para el límite por versión: cada página HTML prerenderida, cada bundle JS y CSS con hash, cada imagen y cada stub de redirección. No hay una cuota aparte para las páginas que generó tu framework. En un sitio programático, el número de páginas es el que se mueve, así que cuenta el output compilado, no tu árbol de código.

¿Por qué un build que pasa en local falla en el contenedor de build de Cloudflare?

Porque la memoria que tu build puede usar no es la que el contenedor publica. Cloudflare publica 8 GB para un Workers Build, pero el heap por defecto de Node no es ese número — V8 lo deriva de la máquina que encuentra, así que el mismo build tiene un margen distinto en un laptop que dentro del contenedor. Fija el heap de forma explícita con NODE_OPTIONS y dimensiónalo al presupuesto real del contenedor, no al laptop.

Artículos Relacionados