Lección 3 de 312 min
Cloudflare Workers y el edge
Código que se ejecuta en cientos de ciudades a la vez: isolates de V8, el manejador fetch, bindings y límites.
Tu servidor de Express vive en un centro de datos de Virginia. Para un usuario de Nueva York la respuesta llega enseguida, pero alguien en Buenos Aires o en Madrid espera a que cada petición cruce un océano de ida y otro de vuelta. Puedes alquilar servidores en varias regiones, pero entonces tienes que desplegar, vigilar y escalar cada uno.
Cloudflare Workers propone otra cosa: subes tu código una vez y se ejecuta en los centros de datos de Cloudflare repartidos por cientos de ciudades, en el más cercano a cada usuario. En esta lección verás qué es «el edge», por qué los Workers arrancan casi al instante y cómo se escribe, se configura y se publica uno.
El edge y los isolates
Qué es «el edge»
Ejecutar el código en el borde de la red, cerca del usuario, no en una región central.
- Lo contrario:
- Una región central
El edge («borde») es la parte de la red más cercana a los usuarios: los cientos de centros de datos que las CDN tienen repartidos por el mundo. Al principio solo guardaban copias de archivos estáticos; hoy también ejecutan código. Una petición desde Madrid la atiende un servidor cercano, en lugar de viajar hasta otro continente.
La distancia importa porque la luz por fibra tarda un tiempo fijo en recorrerla, y cada petición hace varios viajes de ida y vuelta. Reducir la distancia reduce la latencia de forma que ninguna optimización de tu código puede igualar.
Úsalo cuando
Para lo que tiene que responder rápido en todo el mundo: redirecciones, autenticación en la entrada, personalización por país, APIs ligeras o páginas renderizadas en el servidor.
Ten en cuenta
Ejecutar cerca del usuario no sirve de mucho si cada petición consulta una base de datos que está lejos: la latencia simplemente se traslada. Piensa dónde viven los datos, no solo el código.
Servidor en una región (Virginia)
Madrid ──── océano ────▶ Virginia ──── océano ────▶ Madrid
varios viajes de ida y vuelta por cada petición
En el edge
Madrid ──▶ centro de datos de Cloudflare cercano ──▶ Madrid
el mismo código, a unos pocos kilómetrosIsolates de V8
Miles de programas aislados dentro de un mismo proceso: arrancan en milisegundos.
- Motor:
- V8
- Runtime:
- workerd (código abierto)
Las plataformas serverless clásicas ejecutan cada función en un contenedor o una máquina virtual: cuando llega una petición y no hay ninguno encendido, hay que arrancarlo, con su sistema operativo y su Node, lo que se llama arranque en frío (cold start) y puede tardar bastante.
Workers usa isolates de V8, el mismo mecanismo que separa las pestañas en Chrome. Un único proceso ejecuta miles de isolates, cada uno con su memoria, completamente aislado de los demás. Crear uno cuesta milisegundos y muy poca memoria, así que el arranque en frío es prácticamente inexistente.
Úsalo cuando
Cuando las peticiones llegan de forma irregular y no quieres que el primer usuario tras un rato de calma espere a que arranque el servidor.
Ten en cuenta
Un isolate no es un servidor que viva para siempre: Cloudflare puede crearlo y destruirlo cuando quiera, y cada ciudad tiene los suyos. No guardes estado en variables globales esperando que persista entre peticiones.
Contenedor / máquina virtual
┌──────────────────────────┐
│ sistema operativo │ arrancar: lento
│ runtime (Node) │ memoria: mucha
│ tu código │
└──────────────────────────┘
Isolates de V8 (un solo proceso)
┌──────────────────────────┐
│ [Worker A] [Worker B] │ arrancar: milisegundos
│ [Worker C] [Worker D] … │ memoria: poca
└──────────────────────────┘Programar un Worker
El manejador fetch
Una función que recibe un Request y devuelve un Response, con APIs web estándar.
- Entrada:
- Request
- Salida:
- Response
Un Worker es un módulo que exporta por defecto un objeto con un método fetch(request, env, ctx). Recibe la petición como un objeto Request estándar (el mismo de la Fetch API del navegador) y debe devolver un Response. No hay app.listen ni puertos: Cloudflare llama a tu función por cada petición.
env contiene la configuración: variables, secretos y bindings a otros servicios. ctx.waitUntil(promesa) permite seguir trabajando después de responder, por ejemplo para guardar una estadística, sin que el usuario espere. Además de fetch, un Worker puede exportar otros manejadores, como scheduled para tareas programadas.
Úsalo cuando
En cualquier Worker. Para muchas rutas, un framework ligero como Hono te da un enrutado al estilo de Express sobre este mismo manejador.
Ten en cuenta
Lo que lanzas sin await ni ctx.waitUntil puede cortarse en cuanto envías la respuesta. Y recuerda que las APIs son las del navegador (Request, Response, URL, crypto.subtle), no las de Node.
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === "/hola") {
const pais = request.cf?.country ?? "algún lugar";
return new Response(`Hola, visitante de ${pais}`);
}
if (url.pathname === "/recetas") {
const { results } = await env.DB.prepare("SELECT * FROM recetas").all();
ctx.waitUntil(registrarVisita(env, url.pathname)); // sigue tras responder
return Response.json(results);
}
return new Response("No encontrado", { status: 404 });
},
} satisfies ExportedHandler<Env>;Bindings: KV, D1, R2, Durable Objects y Queues
Servicios de almacenamiento y mensajería conectados a tu Worker a través de env.
- Se leen desde:
- env
- R2:
- Compatible con S3
Un Worker no tiene disco ni memoria que perdure, así que guarda los datos en servicios de Cloudflare que se conectan mediante bindings: los declaras en la configuración y aparecen en env listos para usar, sin URLs ni claves en el código. KV es un almacén clave-valor global, con lecturas muy rápidas pero consistencia eventual: un cambio puede tardar del orden de un minuto en verse en todo el mundo. D1 es una base de datos SQL basada en SQLite. R2 guarda archivos grandes (imágenes, vídeos, copias de seguridad) y es compatible con la API de Amazon S3.
Durable Objects son objetos con estado de los que existe una sola instancia en el mundo para cada identificador: ideales para coordinar, como una sala de chat o un contador exacto. Queues son colas de mensajes: un Worker envía tareas y otro las procesa después, a su ritmo.
Úsalo cuando
KV para configuración y cachés que se leen mucho y cambian poco; D1 para datos relacionales; R2 para archivos; Durable Objects cuando necesitas consistencia fuerte o coordinación; Queues para trabajo en segundo plano.
Ten en cuenta
No uses KV para algo que debe leerse justo después de escribirse, como un saldo o un stock: otra ciudad puede ver el valor antiguo. Para eso están D1 o Durable Objects.
interface Env {
CACHE: KVNamespace;
DB: D1Database;
FOTOS: R2Bucket;
}
// KV: lecturas rapidísimas, consistencia eventual
await env.CACHE.put("receta:7", JSON.stringify(receta), { expirationTtl: 3600 });
const guardada = await env.CACHE.get("receta:7", "json");
// D1: SQL con parámetros
const fila = await env.DB.prepare("SELECT * FROM recetas WHERE id = ?").bind(7).first();
// R2: archivos grandes
await env.FOTOS.put("gazpacho.jpg", request.body);
const foto = await env.FOTOS.get("gazpacho.jpg");Wrangler
La herramienta de línea de comandos para crear, probar y publicar Workers.
- Configuración:
- wrangler.jsonc o wrangler.toml
Wrangler es la CLI oficial. wrangler dev ejecuta tu Worker en local con el mismo runtime que en producción, con recarga automática y versiones locales de KV, D1 y R2. wrangler deploy lo publica en toda la red de Cloudflare. También crea recursos (wrangler d1 create), guarda secretos cifrados (wrangler secret put) y muestra los logs en vivo (wrangler tail).
La configuración vive en un archivo en la raíz del proyecto, wrangler.toml o, en los proyectos recientes, wrangler.jsonc. Ahí indicas el nombre, el archivo de entrada, una fecha de compatibilidad (que fija el comportamiento del runtime para que una actualización no cambie tu Worker) y los bindings.
Úsalo cuando
Siempre. Para empezar un proyecto, npm create cloudflare@latest genera la estructura, la configuración y los tipos.
Ten en cuenta
Los secretos no van en el archivo de configuración, que se sube a Git: guárdalos con wrangler secret put y, en local, en un archivo .dev.vars que no se versiona. Ejecuta wrangler types para generar la interfaz Env a partir de tus bindings.
// wrangler.jsonc
{
"name": "api-recetas",
"main": "src/index.ts",
"compatibility_date": "2026-10-01",
"compatibility_flags": ["nodejs_compat"],
"kv_namespaces": [{ "binding": "CACHE", "id": "<id>" }],
"d1_databases": [{ "binding": "DB", "database_name": "recetas", "database_id": "<id>" }]
}
// npx wrangler dev → http://localhost:8787
// npx wrangler secret put CLAVE → secreto cifrado
// npx wrangler deploy → publicado en toda la red
// npx wrangler tail → logs en vivoNota
El patrón fetch(request) → Response no es exclusivo de Cloudflare: Deno, Bun y otras plataformas del edge usan la misma forma, basada en estándares web. Lo que aprendes aquí se traslada casi tal cual.
Límites y compatibilidad
Límites y nodejs_compat
No es un Node completo: tiempo de CPU, memoria y APIs acotados.
- Opción:
- nodejs_compat
- Límite clave:
- Tiempo de CPU
Un Worker tiene límites que un servidor no tiene: el tiempo de CPU por petición está acotado (muy poco en el plan gratuito; más, y configurable, en los de pago), la memoria de cada isolate es limitada y el código desplegado no puede pasar de cierto tamaño. Lo que cuenta es el tiempo de cálculo: esperar a un fetch o a una consulta no consume CPU.
El runtime ofrece APIs web, no las de Node. Con la opción nodejs_compat en compatibility_flags se activan muchos módulos de Node, como node:buffer, node:crypto o node:stream, y con ellos funcionan muchos paquetes de npm. Pero no todos: no hay un disco donde guardar archivos de forma permanente ni puedes lanzar otros procesos.
Úsalo cuando
Activa nodejs_compat en cuanto uses librerías pensadas para Node. Y consulta la página de límites antes de diseñar algo que calcule mucho o maneje archivos muy grandes en memoria.
Ten en cuenta
Para tareas que calculan durante minutos, como transcodificar vídeo, o que necesitan programas del sistema, un Worker no es la herramienta: usa un servidor o contenedor tradicional y, si quieres, deja el Worker delante como puerta de entrada.
import { Buffer } from "node:buffer";
import { createHash } from "node:crypto";
export default {
async fetch(request) {
const texto = await request.text();
const huella = createHash("sha256").update(texto).digest("hex");
const base64 = Buffer.from(texto).toString("base64");
return Response.json({ huella, base64 });
},
};
// No disponible: lanzar otros procesos (child_process)
// ni guardar archivos en un disco que persistaAtención
Los límites concretos (milisegundos de CPU, megas de memoria, tamaño del código) dependen del plan y cambian con el tiempo. Compruébalos siempre en la documentación oficial antes de decidir.
Interactivo
Servidor Node frente a Cloudflare Workers
Activa o desactiva opciones para compararlas cara a cara.
| Característica | Servidor Node (Express) | Cloudflare Workers |
|---|---|---|
| Dónde se ejecuta | En las máquinas o la región que elijas | En cientos de ciudades, cerca del usuario |
| Arranque en frío | Ninguno si está siempre encendido; en contenedores bajo demanda puede tardar | Casi nulo: un isolate arranca en milisegundos |
| Estado en memoria | Sí: el proceso vive mucho tiempo | No fiable: usa KV, D1, R2 o Durable Objects |
| APIs disponibles | Todas las de Node y cualquier paquete de npm | APIs web estándar y parte de Node con nodejs_compat |
| Escalado | Lo configuras tú o tu plataforma | Automático |
| Límites | Los de tu máquina | Tiempo de CPU, memoria y tamaño del código acotados |
Ponlo en práctica
Saber qué es cada cosa es la mitad del trabajo. La otra mitad es reconocer cuándo usarla.
Interactivo
¿Qué usarías?
Lee cada situación y elige la opción que mejor la resuelve. Fallar aquí no cuenta: es para practicar.
Tu tienda vende en todo el mundo y quieres redirigir a cada visitante a la versión de su país en cuanto entra, con el menor retraso posible.
Para recordar
- El edge ejecuta tu código en el centro de datos más cercano al usuario, y eso reduce la latencia más que cualquier optimización.
- Los Workers usan isolates de V8, no contenedores: arrancan en milisegundos, pero no conservan estado entre peticiones.
- Un Worker exporta
fetch(request, env, ctx)y responde con unResponse, usando APIs web estándar. - Los datos van en bindings: KV (rápido, eventual), D1 (SQL), R2 (archivos), Durable Objects (estado consistente) y Queues (colas).
- No es un Node completo: hay límites de CPU y memoria, y
nodejs_compatactiva solo parte de las APIs de Node.
Comprueba lo aprendido
Cuestionario
Responde las 5 preguntas para completar la lección.
1.¿Por qué los Workers casi no tienen arranque en frío?
2.Guardas un valor en KV desde Madrid y, un segundo después, un usuario de Tokio lo lee. ¿Qué puede pasar?
3.¿Para qué sirve
ctx.waitUntil()en un Worker?4.Cuentas las visitas en una variable global
let visitas = 0de tu Worker. ¿Por qué el número no es fiable?5.¿Qué hace la opción
nodejs_compat?