wandres.dev
BINDINGS · el modelo de acceso

Tipos de bindings

El catálogo de capacidades que un Worker puede recibir: almacenamiento (KV, R2, D1, Durable Objects), mensajería y cómputo entre Workers (Queues, service bindings), inteligencia (Workers AI, Vectorize) y configuración (secretos y variables). Qué poder concede cada uno y qué tipo de cliente aparece en env.

⏱ 16 min

Todos los bindings comparten el mismo modelo de acceso —los declaras y aparecen en env—, pero no todos conceden el mismo poder. Uno te da un almacén de claves y valores; otro, una base de datos SQL; otro, la capacidad de invocar a otro Worker o a un modelo de IA. Conocer el catálogo no es memorizar una lista de productos, sino aprender a mapear cada necesidad de tu aplicación a la capacidad mínima que la satisface.

🎯 Al terminar esta lección sabrás
  • Clasificar los bindings por la capacidad que otorgan, no solo por el nombre del producto.
  • Reconocer los bindings de almacenamiento: KV, R2, D1 y Durable Objects.
  • Reconocer los de mensajería y cómputo: Queues y service bindings.
  • Reconocer los de inteligencia y configuración: AI, Vectorize, secretos y variables.

Almacenamiento: cuatro formas de recordar

El grupo más numeroso concede persistencia, pero cada miembro almacena una forma distinta de dato y expone un cliente distinto en env. Elegir bien empieza por reconocer qué modela cada uno.

🗝️

KV — env.MI_KV

Un almacén de claves y valores replicado globalmente. Su cliente es un KVNamespace con get y put. Lecturas rapidísimas y eventualmente consistentes: ideal para configuración y caché.

🪣

R2 — env.MI_BUCKET

Almacenamiento de objetos —archivos, imágenes, blobs— sin cargos de egress. Su cliente es un R2Bucket. Para lo grande y no estructurado que servirías desde un bucket S3.

🗃️

D1 — env.DB

Una base de datos SQLite en el edge. Su cliente es un D1Database con prepare y SQL completo. Para datos relacionales con consultas ricas.

🧭

Durable Objects — env.SALA

Estado coordinado con identidad única y consistencia fuerte. El binding es un DurableObjectNamespace desde el que obtienes el stub de una instancia concreta. Para lo que exige un único punto de verdad.

La distinción de fondo es el modelo de consistencia. KV sacrifica consistencia inmediata por velocidad global; D1 te da transacciones SQL; y un Durable Object es la herramienta cuando necesitas que una entidad —una sala de chat, un contador, una sesión— tenga un dueño único que serialice sus cambios sin condiciones de carrera.

Mensajería y cómputo entre Workers

No todos los bindings apuntan a un almacén. Dos de ellos conceden la capacidad de comunicar piezas de cómputo entre sí, dentro de la red de Cloudflare y sin pasar por la internet pública.

Un binding a Queues te convierte en productor de una cola: env.MI_COLA.send(mensaje) encola trabajo que otro Worker —el consumidor— procesará después, de forma asíncrona y con reintentos. Es el desacople clásico entre quien pide y quien ejecuta.

Un service binding te da una referencia a otro Worker y te deja invocarlo directamente, como si sus métodos fueran locales. La llamada no sale a la red pública: viaja por la infraestructura interna, sin latencia de ida y vuelta por internet ni necesidad de autenticar una API.

export default {
  async fetch(request, env, ctx): Promise<Response> {
    // productor de una cola: encola y sigue
    await env.MI_COLA.send({ tipo: 'email', a: 'ada@ejemplo.com' });

    // service binding: invoca a otro Worker sin salir a internet
    const respuesta = await env.AUTH.fetch(request);
    return respuesta;
  },
} satisfies ExportedHandler<Env>;
ℹ️
Un service binding es composición, no red

La diferencia entre llamar a otro Worker por su URL pública y hacerlo por un service binding es la misma que hay entre invocar un microservicio por HTTP e importar una función. El binding compone Workers como piezas de un solo sistema: sin DNS, sin TLS, sin credenciales de API, sin salir del recinto de Cloudflare. Es la base para partir una aplicación en Workers pequeños y especializados sin pagar el peaje de la red entre ellos.

Inteligencia y configuración

El último grupo mezcla lo más nuevo de la plataforma con lo más básico. Comparten que también son capacidades declaradas, aunque su forma sea muy distinta entre sí.

🧠

AI — env.AI

Acceso a Workers AI para ejecutar inferencia sobre modelos alojados en la red. Su cliente es un Ai, y lo usas con env.AI.run(modelo, entrada).

🔎

Vectorize — env.VEC

Un índice de vectores para búsqueda semántica y clasificación. El cliente expone insert y query sobre embeddings; es la pieza de recuperación en un sistema RAG.

🔒

Secretos — env.MI_SECRETO

Valores cifrados —claves de API, tokens—. En env aparecen como cadenas de texto, pero no se guardan en la configuración versionada: se suben aparte.

🏷️

Variables — env.MODO

Valores de texto plano no sensibles —un nombre de entorno, un flag—. Se declaran en la config y llegan a env como cadenas.

La inteligencia merece verse en código, porque es donde el modelo de acceso más sorprende: pides inferencia o una búsqueda vectorial con el mismo gesto con el que leerías una clave de configuración.

// pedir a un modelo y consultar un indice se hacen como cualquier binding
const salida = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
  prompt: 'Resume el edge en una frase',
});
const vecinos = await env.VEC.query(vectorConsulta, { topK: 3 });

Secretos y variables son el recordatorio de que incluso una simple cadena de configuración entra por el mismo conducto que un cliente de base de datos. La diferencia entre ambos es la sensibilidad y el lugar donde viven: la variable es pública y va en la configuración; el secreto es cifrado y se sube por un canal aparte para que nunca aparezca en el repositorio.

💡
El catálogo no acaba aquí

Hay más capacidades que siguen el mismo patrón: Hyperdrive acelera bases de datos SQL externas, el binding de assets sirve archivos estáticos, Browser Rendering te da un navegador headless y Analytics Engine recibe eventos de telemetría. No necesitas memorizarlas: basta con saber que, cuando aparezca una capacidad nueva, se declarará en la config y llegará a env igual que todas las demás.

flowchart TD
ENV[env] --> ALM[Almacenamiento]
ENV --> MSG[Mensajeria y computo]
ENV --> IA[Inteligencia]
ENV --> CFG[Configuracion]
ALM --> A1[KV R2 D1 Durable Objects]
MSG --> M1[Queues y service bindings]
IA --> I1[Workers AI y Vectorize]
CFG --> C1[secretos y variables]
style ENV fill:#89b4fa,color:#11111b
style A1 fill:#a6e3a1,color:#11111b
style M1 fill:#a6e3a1,color:#11111b
style I1 fill:#a6e3a1,color:#11111b
style C1 fill:#a6e3a1,color:#11111b
La lista de tipos oculta una sola idea: todo poder externo es un binding

Al principio el catálogo parece una colección heterogénea —un almacén de claves, una base de datos, una cola, otro Worker, un modelo de IA, un secreto— y la tentación es memorizarlo como quien memoriza un menú de productos. Pero mira lo que tienen en común y verás la arquitectura entera de la plataforma en una frase: cualquier capacidad que tu Worker no tenga por sí mismo —recordar, comunicarse, pensar, configurarse— llega como un binding, se declara igual y aparece en env igual. Esa uniformidad es una decisión de diseño con consecuencias hondas. Primero, hace plano el espacio de diseño: no hay recursos de primera clase y recursos de segunda, un modelo de IA se enchufa con el mismo gesto que una variable de texto, y por eso añadir una capacidad nueva a un Worker nunca te obliga a aprender un mecanismo de acceso nuevo. Segundo, convierte la elección técnica en una elección de capacidades mínimas: la pregunta deja de ser qué producto de Cloudflare uso y pasa a ser qué poder concreto necesita esta pieza —recordar poco y rápido apunta a KV, coordinar una entidad única apunta a un Durable Object, desacoplar trabajo apunta a Queues— de modo que el catálogo funciona como un mapa de intenciones, no de marcas. Tercero, y por eso importa clasificar y no solo enumerar, la taxonomía real no es KV frente a R2 frente a D1, sino estado frente a mensajería frente a inteligencia frente a configuración: cuatro necesidades arquitectónicas, cada una con sus herramientas. Cuando dejas de ver diez productos sueltos y empiezas a ver cuatro ejes de necesidad servidos por un único modelo de acceso, la plataforma se te vuelve legible: ya no eliges bindings por costumbre, sino que traduces cada requisito de tu sistema a la capacidad más pequeña que lo cumple, confiando en que la vía para pedirla siempre será la misma.

⚔️ Traduce necesidades a capacidades
  1. Escribe tres necesidades de una app real —por ejemplo, guardar sesiones, servir imágenes y coordinar una subasta en vivo— y asigna a cada una el binding mínimo que la cubre.
  2. Justifica una elección de consistencia: explica por qué la subasta pide un Durable Object y no un KV.
  3. Diseña un caso para un service binding: parte una función en dos Workers y describe qué gana la llamada al no salir a internet.
  4. Clasifica cada uno de tus tres bindings elegidos en uno de los cuatro ejes —estado, mensajería, inteligencia, configuración— y comprueba que la vía de acceso es idéntica en todos.