wandres.dev
WORKERS AI · inferencia en el edge

Qué es Workers AI: inferencia sobre GPUs serverless

Workers AI pone una flota de GPUs repartidas por la red de Cloudflare al alcance de una llamada de función. No hay servidor de inferencia que aprovisionar, ni imagen con drivers que mantener, ni pesos de varios gigabytes que descargar, ni tarjeta ociosa que siga facturando de madrugada. Qué significa exactamente serverless aplicado a la inferencia, qué desaparece de tu lista de responsabilidades, por qué el acceso es un binding y no una clave de API, y dónde ocurre de verdad el cómputo cuando tu Worker vive en cientos de ubicaciones a la vez.

⏱ 15 min

Durante años, poner un modelo en producción significaba una cadena larga y cara: elegir una instancia con GPU, pelearse con drivers y versiones de CUDA, empaquetar pesos de varios gigabytes, mantener el servicio caliente para no pagar arranques de minutos, y vigilar que la factura no se disparase mientras la tarjeta estaba ociosa la mitad del día. Workers AI borra esa cadena entera. Cloudflare ha distribuido GPUs por su propia red y las expone como aquello que ya sabes manejar: un binding. Tu Worker escribe una línea, env.AI.run, y al otro lado hay hardware acelerado que no aprovisionas, no escalas y no apagas.

🎯 Al terminar esta lección sabrás
  • Definir Workers AI como inferencia serverless sobre GPUs distribuidas en la red de Cloudflare.
  • Enumerar qué responsabilidades desaparecen al no gestionar infraestructura de inferencia.
  • Entender por qué el acceso es un binding y no una clave de API con su cadena de secretos.
  • Situar dónde ocurre realmente el cómputo y qué implica eso para la latencia.

Inferencia sin infraestructura

La palabra serverless se ha usado tanto que ha perdido filo, así que conviene decir exactamente qué desaparece. En una inferencia autogestionada tú eres responsable de una pila entera: la máquina con GPU y su disponibilidad, el sistema operativo y los drivers, el runtime de inferencia, la descarga de los pesos del modelo, su carga en la memoria de la tarjeta, la política de autoescalado cuando llega el pico, el apagado cuando no llega nadie, y la aritmética incómoda de que una GPU parada cuesta prácticamente lo mismo que una GPU trabajando.

Workers AI se queda con toda esa pila. Los modelos del catálogo ya están desplegados y con sus pesos residentes en las tarjetas, así que no hay arranque en frío de minutos: la primera petición del día se atiende como la milésima. No hay capacidad que reservar ni instancia que dimensionar, porque no existe una máquina tuya; hay una flota compartida a la que tus peticiones entran y salen. Y no hay coste ocioso, porque se factura por trabajo realizado y no por tiempo de tarjeta encendida.

Ese último punto es el que más cambia la economía de los proyectos pequeños y medianos, y conviene entender por qué. Una GPU dedicada solo sale a cuenta si la mantienes ocupada, de modo que el modelo autogestionado premia el tráfico alto y constante y castiga con dureza al irregular: si tu carga llega a ráfagas, pagas la tarjeta entera para usarla un rato. El modelo por consumo elimina esa penalización y hace viables funciones que nunca habrían justificado su propia infraestructura —una clasificación que se ejecuta cien veces al día, una transcripción ocasional, un resumen semanal—, que es precisamente donde vive la mayoría del software real.

El precio de esa comodidad es una restricción honesta que conviene tener clara desde la primera línea: ejecutas los modelos del catálogo de Cloudflare, no cualquier archivo de pesos que se te ocurra. Puedes afinar el comportamiento con adaptadores LoRA sobre modelos soportados, pero si tu proyecto exige un modelo propio entrenado desde cero, la respuesta correcta no es Workers AI sino un Container o un proveedor externo. Conocer ese límite desde el principio te ahorra la frustración de descubrirlo a mitad de camino.

Merece la pena hacer explícito el intercambio, porque es el mismo que ya aceptaste en otras piezas de la plataforma. Con D1 renunciaste a elegir el motor a cambio de no administrar una base. Con Workers renunciaste a controlar el proceso a cambio de no tener cold starts. Aquí renuncias a elegir los pesos a cambio de no tener infraestructura de GPU. En los tres casos la operación es la misma: cedes una libertad que casi nunca ibas a ejercer y recuperas un tiempo que sí ibas a gastar.

Activarlo es una entrada en el manifiesto y nada más. No hay recurso que crear, ni región que elegir, ni credencial que generar.

// wrangler.jsonc
{
  "name": "mi-worker-ia",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-01",
  "ai": {
    "binding": "AI"
  }
}

Con eso, el objeto env de tu manejador gana una propiedad AI cuyo método run es toda la superficie que necesitas para empezar.

export default {
  async fetch(request, env, ctx): Promise<Response> {
    const salida = await env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
      prompt: "Explica en una frase que es el edge",
    });
    return Response.json(salida);
  },
} satisfies ExportedHandler<Env>;

Merece la pena detenerse en lo que no aparece ahí: ninguna URL de endpoint, ninguna cabecera de autorización, ningún cliente que instalar desde npm, ningún secreto. La inferencia ha quedado reducida a una llamada de método sobre un objeto que el runtime te entrega ya construido.

Y como no hay dependencia que instalar, tampoco hay peso que añadir al bundle. En un entorno donde el tamaño del despliegue es un límite real, que la capacidad de IA no cueste ni un kilobyte de JavaScript empaquetado no es un detalle menor: el modelo no viaja contigo, vive al otro lado del binding.

Un binding, no una clave de API

Que el acceso sea un binding y no una clave no es un detalle de ergonomía: es la misma decisión de diseño que recorre toda la plataforma, capacidades en lugar de credenciales, aplicada ahora a la IA. Una clave de API es un secreto portátil: viaja, se copia, se filtra en un repositorio, hay que rotarla, hay que decidir dónde guardarla y hay que confiar en que nadie la exfiltre desde el cliente. Un binding no es portátil por construcción: solo existe dentro del isolate que lo declaró, no se puede extraer del bundle porque no es un valor sino un canal, y el permiso está atado al despliegue y no a una cadena de caracteres.

Las consecuencias prácticas se acumulan deprisa. No hay secreto que rotar ni que auditar. La petición no sale de la red de Cloudflare hacia un tercero, así que no pagas egress ni atraviesas internet pública con el texto de tus usuarios. La facturación llega en la misma cuenta y en la misma factura que el resto de tu proyecto, sin un panel aparte con su propio método de pago. Y el desarrollo local funciona igual: wrangler dev te da el mismo binding, encaminando las llamadas a GPUs reales, de modo que lo que pruebas en tu máquina es exactamente lo que se ejecutará en producción.

Hay además una ganancia de tipado que se nota desde el primer minuto. Al regenerar los tipos, el binding aparece en tu interfaz Env con la firma completa, y el editor conoce qué entradas acepta cada modelo y qué forma tiene su salida.

npx wrangler types
// worker-configuration.d.ts, generado: el binding ya es parte del contrato
interface Env {
  AI: Ai;
}

Eso convierte una clase entera de errores —una clave mal escrita en las entradas, una propiedad inexistente en la respuesta— en fallos de compilación en lugar de en sorpresas a las tres de la mañana. Es la misma ventaja que ya tenías con KV, D1 o R2, y por la misma razón: cuando el acceso se declara en el manifiesto, la herramienta puede razonar sobre él.

💡
El binding es también la unidad de razonamiento sobre permisos

Cuando quieras responder a la pregunta de quién puede invocar modelos en tu cuenta, no busques una lista de claves activas: mira qué Workers declaran el binding ai en su manifiesto. La superficie de acceso es el conjunto de despliegues, no un llavero disperso entre entornos, variables y capturas de pantalla de hace seis meses. Esa es la ganancia silenciosa de las capacidades sobre las credenciales.

Dónde ocurre el cómputo

Aquí es donde conviene afinar el modelo mental, porque la intuición engaña. Tu Worker se ejecuta cerca del usuario, en cualquiera de los cientos de ubicaciones de la red. Las GPUs, en cambio, no están en todas: son hardware caro y viven en un subconjunto de centros de datos. Cuando llamas a env.AI.run, la plataforma encamina la inferencia a una ubicación con capacidad para ese modelo, que puede no ser la misma en la que corre tu código.

Que ese encaminamiento sea invisible tiene una virtud enorme y una consecuencia que hay que aceptar. La virtud es la homogeneidad: escribes el mismo código y obtienes la misma capacidad desde Madrid, desde São Paulo o desde Singapur, sin desplegar nada distinto en cada sitio ni mantener una tabla de qué región tiene qué hardware. La consecuencia es que renuncias a controlar dónde ocurre exactamente el cómputo, algo que importa poco para la latencia pero que conviene tener presente si te rigen requisitos estrictos de residencia de datos.

flowchart LR
U[Usuario] --> W[Worker en el edge cercano]
W -->|env.AI.run| B[Binding AI]
B --> G[GPU en un centro de datos con capacidad]
G --> B
B --> W
W --> U
style B fill:#89b4fa,color:#11111b
style G fill:#fab387,color:#11111b

Esto no es una decepción, es una calibración. En una inferencia, el salto de red interno pesa muy poco comparado con el tiempo que el modelo tarda en generar: unas decenas de milisegundos frente a cientos o miles. Optimizar la distancia a la GPU sería optimizar el sumando pequeño. Lo que sí conviene interiorizar es que el edge te da dos cosas distintas y no debes confundirlas: cercanía al usuario para todo lo que rodea a la inferencia —recibir la petición, autenticar, buscar contexto, componer la respuesta, transmitirla— y acceso homogéneo a la capacidad de cómputo desde cualquier punto de la red. La primera es tuya y la controlas; la segunda te la resuelven.

De ahí se sigue una consecuencia práctica para el diseño: si la inferencia va a dominar el tiempo total de la petición, no tiene sentido pelearse por veinte milisegundos en el resto del camino. El esfuerzo rinde mucho más en dos sitios distintos. El primero, reducir el propio tiempo de generación eligiendo bien el modelo y acotando la longitud de la respuesta. El segundo, dejar de hacer esperar al usuario por lo que ya está listo, transmitiendo la respuesta según se produce en lugar de retenerla hasta el final. Ambas ideas ocupan los niveles siguientes, y las dos importan más que la geografía de la tarjeta gráfica.

Cómo encaja con el resto de la plataforma

Workers AI rara vez se usa sola, y su valor real aparece cuando se combina con las piezas que ya conoces. Que todo comparta runtime, despliegue y facturación convierte lo que en otras plataformas sería una integración con cuatro proveedores en un solo proyecto con cuatro bindings.

🧭

Con Vectorize

Generas embeddings con un modelo del catálogo y los guardas en un índice vectorial para buscar por significado. Es la base de la recuperación semántica y el primer tramo de cualquier arquitectura RAG.

🗂️

Con R2 y D1

R2 guarda los originales —documentos, audios, imágenes— y D1 el texto y los metadatos con los que compones el contexto. El modelo aporta el juicio; el almacenamiento aporta los hechos.

📬

Con Queues y Workflows

La inferencia pesada o diferida no debería vivir en el camino de la petición. Una cola absorbe los picos y un Workflow orquesta procesos de varios pasos con reintentos y estado durable.

🛡️

Con AI Gateway

Delante de las llamadas, un gateway te da caché, límites de ritmo, reintentos, rutas de reserva y analítica de coste, tanto para los modelos del catálogo como para proveedores externos.

Ese encaje es lo que distingue a una demo de un sistema. Una demo llama a un modelo y muestra el resultado; un sistema decide dónde viven los datos que alimentan al modelo, qué se hace en el momento y qué se difiere, qué se cachea, qué se registra y qué ocurre cuando la inferencia falla. Los niveles siguientes recorren exactamente esas decisiones.

ℹ️
La IA es una pieza más, no un producto aparte

Merece la pena resistirse a tratar la inferencia como un módulo separado con su propio subsistema, su propia configuración y su propio equipo. En esta plataforma es un binding entre otros, y su código convive con el de la base de datos y el del almacenamiento en el mismo manejador, el mismo despliegue y la misma observabilidad. Cuanto antes deje de ser un anexo en tu arquitectura y pase a ser una operación normal dentro de tu lógica, antes empezarás a usarla donde de verdad aporta.

La inferencia deja de ser un sistema y pasa a ser una llamada de función

Hay un patrón que se repite en la historia de la computación y que Workers AI vuelve a ejecutar con una limpieza casi didáctica: una capacidad nace como un sistema que hay que montar, y madura hasta convertirse en una primitiva que se invoca. La persistencia fue durante décadas un servidor de base de datos que alguien administraba, con sus copias, sus versiones y su noche de guardia, hasta que se volvió una consulta contra un servicio que nadie ve. El almacenamiento de archivos fue un disco con su RAID y su vigilancia de espacio, hasta que se volvió put y get contra un bucket. La inferencia va por el mismo camino, y ahora mismo estamos justo en el pliegue: hasta anteayer, poner un modelo en producción era un proyecto de infraestructura con su propio equipo, su presupuesto de hardware y su gráfica de utilización de GPU; hoy es una línea dentro de un manejador fetch. Lo profundo no es la comodidad, es lo que la comodidad reordena. Cuando una capacidad cuesta un proyecto, la usas donde el proyecto se justifica: un puñado de funciones grandes, pensadas, defendidas ante alguien. Cuando cuesta una línea, la usas donde tenga sentido, y de repente tiene sentido en sitios que nunca habrías considerado —clasificar un comentario antes de guardarlo, redactar un resumen en el propio camino de la petición, transcribir un audio cuando llega, decidir si dos textos hablan de lo mismo—. La IA deja de ser una feature con mayúsculas, un sitio al que el usuario va, y se disuelve en el tejido de la aplicación como una operación más entre otras. Ese es el cambio que hay que ver ahora, antes de aprender ni una API: no es que sea más fácil hacer lo que ya hacías, es que se vuelve razonable hacer cosas que antes ni te planteabas. Y como toda primitiva barata, traerá su propia disciplina —cuándo no llamarla, cómo acotar su coste, qué hacer cuando falla, dónde sigue siendo mejor una regla de tres líneas que un modelo de ocho mil millones de parámetros—, porque el peligro simétrico de que la inferencia sea trivial de invocar es empezar a invocarla donde no hacía ninguna falta.

⚔️ Enciende el binding y sitúa la pieza
  1. Añade el bloque ai a tu wrangler.jsonc, regenera los tipos y comprueba que env.AI aparece con autocompletado en tu editor.
  2. Escribe un manejador fetch que invoque un modelo de texto del catálogo y devuelva la salida cruda con Response.json para ver su forma real.
  3. Ejecútalo con wrangler dev y razona por qué funciona sin haber configurado ninguna clave ni ningún endpoint.
  4. Enumera las cinco responsabilidades de una inferencia autogestionada que acabas de no asumir, y di cuál te habría costado más tiempo.
  5. Explica con tus palabras por qué la GPU puede no estar en la misma ubicación que tu Worker y por qué eso apenas afecta a la latencia percibida.