Edge deploys: latencia baja desde cualquier lugar
Por qué edge
Sección titulada «Por qué edge»Tu RAG corre en local, latencia ~150ms por query. Movés a un servidor en Argentina, los usuarios en Argentina siguen viendo ~150ms. Los de Tokio ven ~600ms. Los de Frankfurt ven ~400ms. Latencia global: pésima.
Edge te corre el código en ~300 puntos de presencia distribuidos por el planeta. Latencia desde cualquier lugar del mundo: ~50ms para conectar, más el costo de tu pipeline. Tu RAG se siente igual de rápido para todos.
Tradeoff: edge runtime es V8 isolates, no Node.js. Hay reglas:
- No
fs: no podés leer archivos. (Tu corpus tiene que estar accesible vía HTTP — Qdrant Cloud, R2, KV.) - No
processmodule: no podés leer env de la forma usual. Las vars vienen víaenvargument. - No native deps (binarios .node): solo JavaScript / WASM puro.
- No
require(): solo ESM. fetch()global: lo único que podés usar para network.
Qué del pipeline corre en edge
Sección titulada «Qué del pipeline corre en edge»| Stage | Edge? | Por qué |
|---|---|---|
| Ingest (read corpus, chunk, embed, upsert) | ❌ | Toca filesystem. Queda en Node. |
| Refresh | ❌ | Igual que ingest. |
| Query — embed | ✅ | Solo fetch() al endpoint del embedder. |
| Query — retrieve | ✅ | fetch() al REST API de Qdrant. |
| Query — generate | ✅ | fetch() al endpoint del LLM. |
| Query — rerank/multi-query/rewrite | ✅ | También fetch puro. |
Patrón resultante: dos deploys. Un cron job en Node (Cloudflare Cron Trigger, Vercel Cron, Lambda scheduled) hace ingest+refresh. Un Worker en edge atiende las queries.
El handler edge
Sección titulada «El handler edge»packages/01-vercel-ai-sdk/src/ops/edge.ts — ~120 líneas, sin imports al stack del repo (solo tipos Env y funciones helper que viven todas en el archivo):
export interface Env { OLLAMA_URL: string; OLLAMA_LLM: string; OLLAMA_EMBED: string; QDRANT_URL: string; QDRANT_API_KEY?: string; COLLECTION?: string;}
export default { async fetch(request: Request, env: Env): Promise<Response> { // 1. POST / → query path // 2. GET /health → simple healthcheck // ... },};Env tiene strings con los endpoints públicos. Esto es la primera diferencia importante con el código local: no podés usar localhost:11434 desde edge — el worker no tiene acceso a tu máquina.
Las 4 funciones helper
Sección titulada «Las 4 funciones helper»async function embed(env: Env, text: string): Promise<number[]> { const res = await fetch(`${env.OLLAMA_URL}/v1/embeddings`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: env.OLLAMA_EMBED, input: text }), }); if (!res.ok) throw new Error(`embed failed: ${res.status}`); const data = await res.json(); return data.data[0].embedding;}
async function retrieve(env: Env, vector: number[], topK: number): Promise<QdrantPoint[]> { const headers: Record<string, string> = { 'Content-Type': 'application/json' }; if (env.QDRANT_API_KEY) headers['api-key'] = env.QDRANT_API_KEY; const res = await fetch( `${env.QDRANT_URL}/collections/${env.COLLECTION ?? 'rag_vercel'}/points/query`, { method: 'POST', headers, body: JSON.stringify({ query: vector, limit: topK, with_payload: true }) }, ); if (!res.ok) throw new Error(`qdrant query failed: ${res.status}`); const data = await res.json(); return data.result.points;}
// generate(...) similarTodo fetch puro. Sin embed() del AI SDK (que requiere Node bindings). Sin QdrantClient (que también). Esto es el AI SDK de bajo nivel: HTTP a una API.
Setup de Cloudflare Workers
Sección titulada «Setup de Cloudflare Workers»1. Tener una cuenta de Cloudflare
Sección titulada «1. Tener una cuenta de Cloudflare»Cuenta gratis en cloudflare.com. El free tier:
- 100k requests/día gratis
- 10ms CPU por request en free, 30ms en paid (paid: $5/mes)
- Sin egress charges
Para self-study, free tier alcanza con sobra.
2. Authenticarse
Sección titulada «2. Authenticarse»pnpm wrangler loginAbre browser, pide autorización, listo. Token persiste en ~/.wrangler/.
3. Configurar wrangler.toml
Sección titulada «3. Configurar wrangler.toml»Hay un sample en packages/01-vercel-ai-sdk/wrangler.toml.example. Copialo:
cp packages/01-vercel-ai-sdk/wrangler.toml.example \ packages/01-vercel-ai-sdk/wrangler.toml(wrangler.toml está gitignorado para que no commitees URLs y secretos por accidente; el .example queda tracked como referencia.)
Editá los valores:
name = "rag-vercel-edge"main = "src/ops/edge.ts"compatibility_date = "2026-05-01"
[vars]OLLAMA_URL = "https://your-llm-host.example.com" # NO localhostOLLAMA_LLM = "llama3.2:3b"OLLAMA_EMBED = "nomic-embed-text"QDRANT_URL = "https://your-qdrant-cluster.qdrant.io"COLLECTION = "rag_vercel"Y los secretos van por separado:
pnpm wrangler secret put QDRANT_API_KEY# pega el valor cuando pregunta4. Deploy
Sección titulada «4. Deploy»cd packages/01-vercel-ai-sdkpnpm wrangler deployOutput:
Total Upload: 8.42 KiBWorker Startup Time: 5 msUploaded rag-vercel-edge (3.15 sec)Deployed rag-vercel-edge triggers (0.83 sec) https://rag-vercel-edge.<your-subdomain>.workers.devY ya está. El worker está vivo en cada PoP de Cloudflare.
Probar el deploy
Sección titulada «Probar el deploy»curl -X POST https://rag-vercel-edge.<your-subdomain>.workers.dev/ \ -H 'Content-Type: application/json' \ -d '{"question": "¿Qué propone Clean Architecture?"}'Output esperado:
{ "answer": "Clean Architecture propone separar las dependencias en capas concéntricas...", "sources": [ { "filename": "clean-architecture.md", "score": 0.7234 }, { "filename": "clean-architecture.md", "score": 0.6118 }, { "filename": "hexagonal-architecture.md", "score": 0.5891 }, { "filename": "solid-principles.md", "score": 0.5102 } ]}Cloudflare Workers AI: el atajo
Sección titulada «Cloudflare Workers AI: el atajo»Si tu modelo está en el catálogo de Cloudflare Workers AI, te ahorrás el host externo del LLM. Bind:
[ai]binding = "AI"Y en el worker:
async function generate(env: Env, prompt: string): Promise<string> { if (env.AI) { const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { prompt }); return response.response; } // fallback al fetch externo (default del archivo)}Ventaja: el LLM corre en la misma red que el worker. Latencia mínima.
Limitación: la cuota gratis de Workers AI es chica. Para producción real, pagás per-neuron.
Lo que NO va en edge (recapitulación)
Sección titulada «Lo que NO va en edge (recapitulación)»- Ingest: queda como Node script ejecutado en cron / build / scheduled worker que SÍ tiene fs. La regla mental: “ingest es batch, query es real-time”.
- Refresh: idem. Cron una vez por día / hora / cuando aplique.
- Eval harness (Nivel 2): queda en Node. Es batch, corre en CI o local.
Lo que viene
Sección titulada «Lo que viene»Tu RAG es:
- Inspectable (Nivel 1).
- Medible (Nivel 2).
- Robusto (Nivel 3).
- Observable, económico, refrescable y deployable a edge (Nivel 4).
El último capítulo es la lista de chequeo antes de mandarlo a producción + el appendix de comandos del curso entero.