wandres.dev
DE PAGES A WORKERS · la convergencia

Empezar hoy: por qué un proyecto nuevo nace en Workers

El cierre del nivel, en clave de decisión. Por qué en 2026 no queda ningún argumento para arrancar un proyecto en Pages, cuál es el patrón recomendado —un repositorio, un `wrangler.jsonc`, assets más handler, bindings declarados y despliegue por versiones—, en qué orden conviene montarlo durante los primeros días, y qué señales indican que ha llegado el momento de partir el artefacto único en varios servicios.

⏱ 19 min

Los cuatro capítulos anteriores explican una convergencia y cómo atravesarla. Este trata la consecuencia, que es más simple y más exigente: si empiezas algo hoy, ya no hay decisión que tomar. Un proyecto nuevo nace en Workers, y el interés se desplaza de elegir plataforma a elegir bien la forma inicial, porque las decisiones de los primeros días son las que más caro cuesta deshacer y las que menos información tienes cuando las tomas. Lo que sigue es el patrón que en 2026 sirve para casi todo —un repositorio, un manifiesto, assets más handler, bindings declarados, despliegue por versiones—, el orden en que conviene montarlo, y las señales concretas que avisan de que ese artefacto único empieza a quedarse pequeño.

🎯 Al terminar esta lección sabrás
  • Argumentar por qué en 2026 un proyecto nuevo no tiene motivos para nacer en Pages.
  • Montar el patrón recomendado: un manifiesto con assets, handler, bindings y despliegue por versiones.
  • Ordenar las decisiones de los primeros días para no pagarlas más tarde.
  • Reconocer las señales que indican que conviene partir el artefacto único en varios servicios.

La decisión ya está tomada

Merece la pena decirlo sin rodeos porque ahorra discusiones de equipo, y porque en una decisión así el coste real no está en elegir mal una vez, sino en volver a debatirlo en cada proyecto nuevo. La convergencia deja el terreno tan despejado que la pregunta de dónde empezar ya no admite matices. Con la paridad cerrada, elegir Pages para algo nuevo significa aceptar tres cosas a cambio de nada. Aceptas una plataforma que recibe correcciones pero no capacidades nuevas, de modo que cualquier necesidad que te aparezca dentro de un año se resolverá en el otro lado. Aceptas un techo: el día que quieras una tarea programada, comunicación directa entre servicios o estado coordinado, tendrás que migrar en medio del proyecto, que es el peor momento posible. Y aceptas trabajar en un modelo distinto del que usa toda la documentación, todos los ejemplos y todo el ecosistema que se publique a partir de ahora.

Lo que no aceptas, y esto es lo relevante, es ningún ahorro. La gratuidad de los assets es idéntica, el plan de pago es compartido, y la comodidad del despliegue automático está cubierta. La única ventaja histórica que quedaba, la ergonomía, dejó de ser una ventaja. Empezar en Workers no es una apuesta por el futuro: es la opción que hoy cuesta menos y mañana cuesta mucho menos.

El error de razonamiento que hay que evitar aquí es tratar la elección como una comparación entre productos actuales. Cuando uno de los dos recibe capacidades nuevas y el otro no, no estás comparando dos estados: estás comparando dos trayectorias. La distancia entre ellas es cero el día que empiezas y crece todos los meses, de modo que el coste de haber elegido mal no se paga al principio, cuando es visible, sino más tarde, cuando el proyecto ya tiene tráfico, dependencias y prisa.

flowchart TD
I[Proyecto nuevo en 2026] --> W[Nace en Workers]
W --> A[Assets estaticos gratis]
W --> S[Renderizado en servidor y API]
W --> B[Bindings a datos y a IA]
W --> C[Cron y tareas diferidas]
A --> U[Un solo artefacto desplegable]
S --> U
B --> U
C --> U
style W fill:#89b4fa,color:#11111b
style U fill:#a6e3a1,color:#11111b

El patrón recomendado

Resuelta la plataforma, queda lo que de verdad importa: con qué forma nace el proyecto. Y aquí la respuesta correcta es sorprendentemente pequeña.

El patrón que sirve para la enorme mayoría de proyectos nuevos cabe en una frase: un repositorio, un wrangler.jsonc, un directorio de build servido como assets y un handler que atiende lo que los assets no resuelven. Todo lo demás son bloques que se añaden a ese manifiesto cuando hacen falta.

npm create cloudflare@latest mi-app
cd mi-app
npx wrangler dev

Lo que hace bueno a ese patrón no es que sea el más potente, sino que crece por acumulación y no por reestructuración. Añadir una base de datos es añadir un bloque; añadir una tarea programada es añadir otro; añadir un modelo de lenguaje, otro más. En ningún momento hay que reorganizar lo anterior, y esa propiedad es la que permite empezar con lo mínimo sin pagar una reescritura cuando el proyecto crece.

El manifiesto resultante refleja esa acumulación con claridad:

{
  "name": "mi-app",
  "main": "src/index.ts",
  "compatibility_date": "2026-03-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": {
    "directory": "./dist",
    "binding": "ASSETS",
    "run_worker_first": ["/api/*"]
  },
  "observability": { "enabled": true },
  "vars": { "ENTORNO": "produccion" },
  "d1_databases": [
    { "binding": "DB", "database_name": "app", "database_id": "..." }
  ],
  "triggers": { "crons": ["0 3 * * *"] }
}
🧱

Un artefacto, un despliegue

Front-end, API y tareas comparten repositorio, versión y objeto env. No hay contratos de red internos que mantener ni despliegues que coordinar entre piezas.

🔀

El coste sigue a las rutas

Lo estático se sirve gratis desde los assets y solo pagas por las rutas que ejecutan código. La lista de run_worker_first es a la vez una decisión de arquitectura y de factura.

🚦

Versiones antes que tráfico

Subir una versión y promoverla son actos distintos. Cada cambio se prueba en su propia URL antes de tocar producción, y revertir es volver a apuntar a la anterior.

La frontera interna que sí conviene trazar desde el principio es la que separa lo que se sirve de lo que se computa. No es una frontera de carpetas ni de servicios: es la lista de rutas que declaras en run_worker_first más la disciplina de mantener la lógica de negocio en módulos que el handler solo invoca. Con esas dos cosas, partir el proyecto más adelante consiste en mover módulos y ajustar una lista, no en desenredar un ovillo.

Y cuando llegue ese momento, la operación es más barata de lo que suele ser en otras plataformas, porque dos Workers pueden hablar entre sí de forma directa, sin salir a la red pública y sin construir una API interna solo para comunicarse. Esa propiedad es la que justifica de verdad empezar con un único artefacto: no se trata de posponer la arquitectura, sino de que dividir siga siendo barato el día que haya evidencia para hacerlo bien.

El orden de los primeros días

Ese patrón no es solo cómodo: es el que la documentación, los ejemplos y las plantillas del ecosistema dan por supuesto a partir de 2026. Trabajar dentro de él significa que cualquier respuesta que encuentres encaja sin traducción, y esa alineación con el camino principal vale mucho más de lo que parece cuando estás atascado un viernes por la tarde.

El patrón no se monta entero el primer día, y el orden importa porque cada pieza que se pospone se paga con interés. La regla general es sencilla de enunciar y difícil de respetar bajo presión: primero lo que es barato hoy y caro después, y al final lo que mejora con información que todavía no tienes.

Un orden que funciona: fija primero compatibility_date y la observabilidad, porque son dos líneas y evitan dos clases de problema difíciles de diagnosticar más tarde. Declara después los bindings que ya sabes que vas a usar y genera los tipos, para que el compilador vigile el objeto env desde el principio. Conecta a continuación el despliegue automático, aunque el proyecto todavía no haga nada: un proyecto que se despliega solo desde el segundo día nunca desarrolla el hábito de desplegarse a mano. Y deja para el final el enrutado fino y las excepciones de run_worker_first, que son las decisiones que más se benefician de conocer el tráfico real.

npx wrangler types
npx wrangler versions upload
npx wrangler versions deploy

Hay una regla implícita en ese orden que conviene explicitar: lo que se pospone debe ser lo que se beneficia de más información, y lo que se adelanta debe ser lo que se vuelve más caro con el tiempo. Fijar una fecha de compatibilidad cuesta una línea hoy y una tarde de arqueología si la descubres tarde. Repartir el proyecto en servicios, en cambio, es una decisión que mejora muchísimo con tres meses de tráfico real delante. El calendario de un proyecto nuevo no es una lista de tareas, es una gestión de esa asimetría.

Los cuatro errores de arranque

Casi todos los proyectos nuevos cometen los mismos cuatro fallos, y los cuatro comparten una estructura: cuestan un minuto el primer día y varias horas el sexto mes. No son errores de conocimiento sino de calendario, y por eso conviene tenerlos escritos.

El primero es no fijar compatibility_date, o fijarla y no volver a mirarla nunca. Esa fecha determina qué comportamientos del tiempo de ejecución ves, y dejarla sin declarar convierte cualquier diferencia entre local y producción en un misterio. Declararla es trivial; revisarla de forma deliberada cada cierto tiempo, con las pruebas delante, es lo que la mantiene útil.

Ese primer error tiene una versión agravada que conviene reconocer: fijar la fecha, ver un aviso de incompatibilidad meses después y adelantarla sin leer qué cambia. La fecha existe para que el cambio de comportamiento sea una decisión con pruebas delante, no un movimiento reflejo para silenciar un mensaje.

El segundo es meter un secreto en vars. Ese bloque es texto plano dentro de un archivo versionado, de modo que una clave puesta ahí queda escrita en el historial del repositorio para siempre, y rotarla después no borra lo que ya se publicó. Los secretos se suben aparte, y esa distinción hay que respetarla desde el primer commit, no desde el primer susto.

El tercero es activar run_worker_first de forma global por comodidad, para que el código vea todas las peticiones. Funciona, y convierte en facturable cada petición de cada imagen de tu sitio. La lista de patrones existe justamente para que esa autoridad se conceda ruta por ruta, y usarla bien es a la vez una decisión de arquitectura y de coste.

Hay una variante del tercero que conviene mencionar porque es más sutil: colocar la lógica de sesión en el handler de forma que toda petición, incluidas las de archivos, tenga que pasar por él. Es la misma factura por otro camino, y se evita comprobando la sesión solo en las rutas que la necesitan y delegando el resto en la maquinaria de assets.

El cuarto es desplegar a mano las primeras semanas con la promesa de automatizarlo después. Un proyecto que nace desplegándose desde un portátil desarrolla dependencias invisibles con ese portátil, y cuando por fin se automatiza aparecen pasos que nadie había escrito en ninguna parte. Conectar el despliegue automático el segundo día, cuando aún no hay nada que perder, es la forma más barata de que nunca exista ese conocimiento no escrito.

💡
Un solo Worker hasta que haya una razón para partirlo

La tentación de dividir el proyecto en varios servicios llega temprano y casi siempre es prematura. Un artefacto único no es una limitación: es la ausencia de un coste que solo merece la pena pagar cuando aparece una razón concreta. Hay tres señales fiables. Que dos partes necesiten desplegarse con cadencias distintas, porque una es estable y la otra cambia cada día. Que una parte tenga un perfil de recursos que perjudica a la otra, como un proceso pesado que compite con las respuestas rápidas. Y que dos equipos distintos se pisen en el mismo repositorio. Cuando llegue alguna, partir es barato porque la comunicación entre Workers es directa; hacerlo antes solo compra complejidad.

La forma inicial de un sistema es la decisión más cara que tomas con menos información

Hay una asimetría incómoda en el centro de todo proyecto nuevo, y conviene mirarla de frente en lugar de esperar a descubrirla: las decisiones estructurales del primer día son las más difíciles de revertir y se toman en el momento de máxima ignorancia. No sabes todavía qué parte crecerá, qué ruta recibirá el noventa por ciento del tráfico, qué necesidad aparecerá en el sexto mes ni qué parte del sistema resultará ser la que nadie quiere tocar. Y sin embargo el primer día decides cuántos artefactos hay, dónde vive cada responsabilidad y qué habla con qué, y esas decisiones sobreviven a casi todo lo demás, porque reescribir una función es una tarde y reordenar las fronteras de un sistema es un trimestre. La respuesta habitual a esa asimetría es intentar adivinar mejor: diseñar por adelantado la arquitectura que el sistema tendrá cuando sea grande, repartir en servicios desde el principio, poner colas entre piezas que todavía no existen. Es una respuesta comprensible y casi siempre equivocada, porque paga hoy, con certeza, el coste de una complejidad que quizá nunca haga falta, y encima fija fronteras basadas en una previsión que aún no puede ser buena. La respuesta mejor es distinta: elegir la forma inicial que mantenga abierto el mayor número de futuros por el menor coste presente. Un artefacto único, con una frontera interna clara entre lo que se sirve y lo que se computa, y con un mecanismo barato para partirlo cuando se sepa por dónde, cumple exactamente ese criterio. No es la arquitectura del sistema grande, y no pretende serlo; es la arquitectura que permite descubrir cuál será esa arquitectura sin pagar por adelantado. El corolario práctico es que la decisión importante del primer día no es cómo repartir el sistema, sino asegurarse de que repartirlo más tarde sea barato: fronteras internas explícitas, despliegue reversible, configuración versionada y observabilidad desde el principio. Cumplido eso, empezar simple deja de ser una concesión a la falta de tiempo y pasa a ser la estrategia deliberada de quien sabe que la información que necesita para decidir bien todavía no ha llegado, y que llegará sola si el sistema está vivo.

⚔️ Arranca un proyecto con el patrón de 2026
  1. Crea un proyecto nuevo y escribe su wrangler.jsonc completo con main, bloque assets, compatibility_date y observabilidad activada.
  2. Añade un binding a datos, genera los tipos y comprueba que el compilador detecta un acceso a un binding no declarado.
  3. Define la lista de run_worker_first para tus rutas de API y justifica, ruta por ruta, por qué esa ruta se computa en lugar de servirse.
  4. Conecta el despliegue automático desde el segundo día y publica una versión de previsualización antes de promover nada a producción.
  5. Escribe de antemano las tres señales que te harán partir este Worker en varios servicios, y guárdalas donde tu equipo las relea dentro de seis meses.