Volver al blog

Edge Computing con JavaScript: Cloudflare Workers, Vercel Edge y Deno Deploy

Hola HaWkers, edge computing está transformando cómo desarrollamos aplicaciones web. En vez de procesar requisiciones en un servidor central distante, el código corre en puntos de presencia distribuidos globalmente, reduciendo latencia drásticamente.

Y lo mejor: puedes usar JavaScript para eso. Vamos a explorar las principales plataformas y entender cuándo usar cada una.

Qué Es Edge Computing

Edge computing mueve la computación para más cerca del usuario final. En vez de una requisición viajar miles de kilómetros hasta un data center central, es procesada en el punto de presencia más próximo.

Beneficios prácticos:

  • Latencia reducida (< 50ms globalmente)
  • Mejor experiencia del usuario
  • Menor carga en el servidor de origen
  • Posibilidad de personalización por región
  • Cold starts prácticamente inexistentes

Casos de uso ideales:

  • APIs de baja latencia
  • Autenticación y autorización
  • Redirecciones inteligentes
  • A/B testing
  • Personalización de contenido
  • Rate limiting
  • Transformación de respuestas

Cloudflare Workers

Cloudflare Workers fue pionero en edge computing con JavaScript. Usa el runtime V8 isolates, que es diferente de Node.js tradicional.

Características

Puntos fuertes:

  • Mayor red de edge (300+ ubicaciones)
  • Cold start prácticamente cero
  • Precio competitivo
  • Ecosistema maduro (KV, Durable Objects, R2)
  • Soporte a WebSockets

Limitaciones:

  • Runtime no es Node.js (algunas APIs diferentes)
  • Límite de CPU time por requisición
  • Curva de aprendizaje para recursos avanzados

Ejemplo Práctico

// src/index.js - Cloudflare Worker
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Ruteo básico
    if (url.pathname === '/api/hello') {
      return new Response(JSON.stringify({
        message: 'Hello from the edge!',
        location: request.cf?.city || 'unknown',
        country: request.cf?.country || 'unknown',
      }), {
        headers: { 'Content-Type': 'application/json' },
      });
    }

    // Cache con KV Storage
    if (url.pathname.startsWith('/api/cached/')) {
      const key = url.pathname.replace('/api/cached/', '');
      const cached = await env.MY_KV.get(key);

      if (cached) {
        return new Response(cached, {
          headers: {
            'Content-Type': 'application/json',
            'X-Cache': 'HIT',
          },
        });
      }

      // Buscar del origin y cachear
      const data = await fetchFromOrigin(key);
      await env.MY_KV.put(key, JSON.stringify(data), {
        expirationTtl: 3600, // 1 hora
      });

      return new Response(JSON.stringify(data), {
        headers: {
          'Content-Type': 'application/json',
          'X-Cache': 'MISS',
        },
      });
    }

    return new Response('Not Found', { status: 404 });
  },
};

async function fetchFromOrigin(key) {
  const response = await fetch(`https://api.origin.com/data/${key}`);
  return response.json();
}

Configuración

# wrangler.toml
name = "my-edge-api"
main = "src/index.js"
compatibility_date = "2025-11-01"

[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"

[vars]
API_KEY = "your-api-key"

Vercel Edge Functions

Vercel Edge Functions se integra perfectamente con Next.js y otros frameworks. Usa el mismo runtime V8 isolates.

Características

Puntos fuertes:

  • Integración nativa con Next.js
  • Deploy automático via Git
  • UI excelente para monitoreo
  • Middleware poderoso
  • Fácil de comenzar

Limitaciones:

  • Menos ubicaciones que Cloudflare
  • Pricing puede escalar rápido
  • Menos recursos de storage nativos

Ejemplo con Next.js

// middleware.ts - Vercel Edge Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const { pathname, geo } = request.nextUrl;

  // Geolocalización
  const country = geo?.country || 'US';
  const city = geo?.city || 'Unknown';

  // Redirección por región
  if (pathname === '/' && country === 'BR') {
    return NextResponse.redirect(new URL('/pt-br', request.url));
  }

  // A/B Testing
  const bucket = request.cookies.get('ab-bucket')?.value;
  if (!bucket && pathname === '/landing') {
    const newBucket = Math.random() < 0.5 ? 'A' : 'B';
    const response = NextResponse.rewrite(
      new URL(`/landing/${newBucket}`, request.url)
    );
    response.cookies.set('ab-bucket', newBucket, {
      maxAge: 60 * 60 * 24 * 30, // 30 días
    });
    return response;
  }

  // Headers customizados
  const response = NextResponse.next();
  response.headers.set('X-Geo-Country', country);
  response.headers.set('X-Geo-City', city);

  return response;
}

export const config = {
  matcher: ['/', '/landing/:path*', '/api/:path*'],
};

Edge API Route

// app/api/edge/route.ts
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('q');

  // Procesamiento leve en el edge
  const results = await searchIndex(query);

  return Response.json({
    results,
    processed_at: new Date().toISOString(),
    edge_location: request.geo?.city,
  });
}

async function searchIndex(query: string | null) {
  // Lógica de búsqueda optimizada para edge
  return [];
}

Deno Deploy

Deno Deploy usa el runtime Deno, ofreciendo TypeScript nativo y APIs modernas.

Características

Puntos fuertes:

  • TypeScript nativo sin build
  • APIs Web estándar (fetch, Request, Response)
  • Deno KV integrado
  • Broadcast Channels para comunicación
  • Free tier generoso

Limitaciones:

  • Ecosistema menor que Node.js
  • Menos integraciones empresariales
  • Curva de aprendizaje si vienes de Node.js

Ejemplo Práctico

// main.ts - Deno Deploy
import { serve } from "https://deno.land/std@0.220.0/http/server.ts";

const kv = await Deno.openKv();

async function handler(request: Request): Promise<Response> {
  const url = new URL(request.url);

  // API de Rate Limiting
  if (url.pathname.startsWith('/api/')) {
    const clientIP = request.headers.get('x-forwarded-for') || 'unknown';
    const rateLimit = await checkRateLimit(clientIP);

    if (!rateLimit.allowed) {
      return new Response(JSON.stringify({
        error: 'Rate limit exceeded',
        retry_after: rateLimit.retryAfter,
      }), {
        status: 429,
        headers: {
          'Content-Type': 'application/json',
          'Retry-After': String(rateLimit.retryAfter),
        },
      });
    }
  }

  // Ruta principal
  if (url.pathname === '/api/data') {
    const data = await fetchData();
    return Response.json(data);
  }

  // Cache con Deno KV
  if (url.pathname.startsWith('/api/cached/')) {
    const key = url.pathname.replace('/api/cached/', '');
    const cached = await kv.get(['cache', key]);

    if (cached.value) {
      return Response.json(cached.value, {
        headers: { 'X-Cache': 'HIT' },
      });
    }

    const data = await fetchFromOrigin(key);
    await kv.set(['cache', key], data, {
      expireIn: 3600 * 1000, // 1 hora
    });

    return Response.json(data, {
      headers: { 'X-Cache': 'MISS' },
    });
  }

  return new Response('Not Found', { status: 404 });
}

async function checkRateLimit(clientIP: string) {
  const key = ['ratelimit', clientIP];
  const now = Date.now();
  const windowMs = 60000; // 1 minuto
  const maxRequests = 100;

  const entry = await kv.get<{ count: number; resetAt: number }>(key);

  if (!entry.value || now > entry.value.resetAt) {
    await kv.set(key, { count: 1, resetAt: now + windowMs });
    return { allowed: true };
  }

  if (entry.value.count >= maxRequests) {
    return {
      allowed: false,
      retryAfter: Math.ceil((entry.value.resetAt - now) / 1000),
    };
  }

  await kv.set(key, {
    count: entry.value.count + 1,
    resetAt: entry.value.resetAt,
  });

  return { allowed: true };
}

async function fetchData() {
  return { message: 'Hello from Deno Deploy!' };
}

async function fetchFromOrigin(key: string) {
  return { key, data: 'origin data' };
}

serve(handler);

Comparativo de las Plataformas

Performance y Red

Plataforma Ubicaciones Cold Start CPU Limit
Cloudflare 300+ ~0ms 50ms
Vercel Edge 100+ ~25ms 25ms
Deno Deploy 35+ ~10ms 50ms

Storage y Recursos

Plataforma KV Storage Durable Objects Database
Cloudflare ✅ KV D1 (SQLite)
Vercel Via Upstash Via integración
Deno ✅ Deno KV Deno KV

Pricing (Tier Gratuito)

Plataforma Requests/día CPU Time Bandwidth
Cloudflare 100k 10ms/req Ilimitado
Vercel 100k - 100GB
Deno 1M/mes - 100GB

Cuándo Usar Edge Computing

Usa Edge Cuando:

  • Necesitas latencia global baja
  • Haces transformación leve de requisiciones
  • Implementas autenticación/autorización
  • Sirves contenido personalizado por región
  • Necesitas rate limiting distribuido
  • Haces redirecciones inteligentes

Evita Edge Cuando:

  • Necesitas procesamiento pesado de CPU
  • Requieres conexión con banco de datos tradicional
  • Tienes dependencias Node.js incompatibles
  • Necesitas procesamiento en batch
  • Tienes requisitos de compliance que exigen región específica

Patrones de Arquitectura

Edge + Origin

// Pattern: Edge como gateway, Origin para lógica pesada
async function handler(request: Request) {
  // Validación rápida en el edge
  const authResult = await validateAuth(request);
  if (!authResult.valid) {
    return new Response('Unauthorized', { status: 401 });
  }

  // Cache check en el edge
  const cacheKey = getCacheKey(request);
  const cached = await cache.get(cacheKey);
  if (cached) {
    return new Response(cached);
  }

  // Forward para origin si es necesario
  const originResponse = await fetch('https://origin.example.com/api', {
    headers: {
      'Authorization': `Bearer ${authResult.token}`,
      'X-User-Id': authResult.userId,
    },
  });

  // Cache response en el edge
  const data = await originResponse.text();
  await cache.put(cacheKey, data, { ttl: 300 });

  return new Response(data);
}

Conclusión

Edge computing con JavaScript ofrece una forma poderosa de mejorar la performance de aplicaciones web. La elección de la plataforma depende de tu contexto:

Cloudflare Workers es ideal para quien necesita la mayor red de distribución y recursos avanzados como Durable Objects.

Vercel Edge Functions es perfecto para proyectos Next.js que quieren integración seamless y buena experiencia de desarrollador.

Deno Deploy es excelente para quien quiere TypeScript nativo y está confortable con el ecosistema Deno.

La buena noticia es que todas las plataformas usan APIs Web estándar, entonces mucho del código es portable entre ellas.

Si estás interesado en explorar más sobre arquitecturas modernas con JavaScript, recomiendo conferir el artículo Node.js vs Deno vs Bun: Cuál Runtime JavaScript Elegir en 2025 para entender mejor los runtimes que alimentan estas plataformas de edge.

¡Vamos a por ello! 🦅

Comentarios (0)

Este artículo aún no tiene comentarios 😢. ¡Sé el primero! 🚀🦅

Añadir comentarios