Volver al blog

Serverless y Edge Computing: El Futuro del Desarrollo Web en 2025

Hola HaWkers, imagina una arquitectura donde no necesitas gestionar servidores, tu aplicación escala automáticamente de 0 a millones de usuarios, y la latencia es siempre inferior a 50ms, no importa dónde esté tu usuario en el mundo.

Bienvenido al futuro que ya es presente: Serverless + Edge Computing.

Entendiendo el Paradigma

Serverless: ¿Qué Cambió?

// Modelo tradicional
const traditionalArchitecture = {
  infrastructure: {
    servers: 'Tú gestionas EC2, containers, etc',
    scaling: 'Manual o auto-scaling groups',
    cost: 'Pagado 24/7, incluso sin uso',
    maintenance: 'Patches, updates, monitoring'
  },

  challenges: [
    'Over-provisioning (desperdicio)',
    'Under-provisioning (crashes)',
    'Complejidad operacional',
    'Cold starts al escalar'
  ]
};

// Modelo serverless
const serverlessArchitecture = {
  infrastructure: {
    servers: 'Zero gestión',
    scaling: 'Automático e instantáneo',
    cost: 'Pagado solo por ejecución',
    maintenance: 'Zero (provider cuida)'
  },

  benefits: [
    'Escala de 0 a infinito automáticamente',
    'Costo proporcional al uso',
    'Deploy en segundos',
    'Foco 100% en código'
  ]
};

Edge Computing: Más Cerca del Usuario

// Traditional: Servidor centralizado
const traditional = {
  user_location: 'São Paulo, Brasil',
  server_location: 'us-east-1 (Virginia, USA)',
  latency: '~200ms', // 😔
  cold_start: '~1000ms'
};

// Edge: Servidor distribuido globalmente
const edge = {
  user_location: 'São Paulo, Brasil',
  server_location: 'Edge node en São Paulo',
  latency: '~15ms', // 🚀
  cold_start: '~0ms (always warm)'
};

Principales Plataformas en 2025

1. Cloudflare Workers

// Cloudflare Worker - Corre en 300+ ciudades globalmente
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Edge KV Storage - Latencia <50ms globalmente
    const value = await env.MY_KV.get(url.pathname);

    if (value) {
      return new Response(value, {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    // Buscar de origen si no cached
    const response = await fetch(`https://api.example.com${url.pathname}`);
    const data = await response.text();

    // Cache en edge para próximos requests
    ctx.waitUntil(env.MY_KV.put(url.pathname, data, {
      expirationTtl: 3600
    }));

    return new Response(data);
  }
};

// Deploy
// wrangler publish
// ✅ Deploy global en < 10 segundos

Casos de uso:

  • API proxies
  • Authentication edges
  • A/B testing
  • Bot protection
  • Geolocation-based routing

2. Vercel Edge Functions

// Vercel Edge Function - Powered by V8 isolates
import { NextRequest, NextResponse } from 'next/server';

export const config = {
  runtime: 'edge',
};

export default async function middleware(req: NextRequest) {
  const country = req.geo?.country || 'US';
  const city = req.geo?.city || 'Unknown';

  // Personalizar respuesta por localización
  if (country === 'BR') {
    return NextResponse.rewrite(new URL('/pt-br', req.url));
  }

  // A/B Testing en edge
  const bucket = Math.random() > 0.5 ? 'A' : 'B';
  const response = NextResponse.next();
  response.cookies.set('bucket', bucket);

  return response;
}

// Edge API Route
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const userId = searchParams.get('userId');

  // Fetch de datos con bajísima latencia
  const response = await fetch(`https://api.example.com/users/${userId}`, {
    // Edge caching
    next: { revalidate: 60 }
  });

  const data = await response.json();

  return Response.json(data);
}

3. AWS Lambda@Edge

// Lambda@Edge - CloudFront edge locations
exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;

  // Detectar dispositivo
  const userAgent = headers['user-agent'][0].value;
  const isMobile = /Mobile/i.test(userAgent);

  // Redirigir para versión optimizada
  if (isMobile && !request.uri.includes('/mobile')) {
    return {
      status: '302',
      headers: {
        location: [{
          key: 'Location',
          value: `/mobile${request.uri}`
        }]
      }
    };
  }

  return request;
};

4. Deno Deploy

// Deno Deploy - TypeScript nativo en edge
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";

const kv = await Deno.openKv();

serve(async (req) => {
  const url = new URL(req.url);

  if (url.pathname === "/api/counter") {
    // KV store en edge
    const count = await kv.get(["counter"]);
    const newCount = (count.value as number || 0) + 1;

    await kv.set(["counter"], newCount);

    return new Response(JSON.stringify({ count: newCount }), {
      headers: { "Content-Type": "application/json" }
    });
  }

  return new Response("Hello from the edge! 🦕");
});

// Deploy: deno deploy --project=myapp main.ts

Arquitectura Serverless Completa

Ejemplo de aplicación full-stack serverless:

// 1. Frontend: Next.js en Vercel
// app/page.tsx
export default async function HomePage() {
  const data = await fetch('https://api.myapp.com/posts', {
    next: { revalidate: 60 } // ISR
  });

  const posts = await data.json();

  return (
    <div>
      {posts.map(post => (
        <PostCard key={post.id} {...post} />
      ))}
    </div>
  );
}

// 2. API: Edge Functions
// app/api/posts/route.ts
export const runtime = 'edge';

export async function GET() {
  // Conectar con database (Planetscale, Neon, etc)
  const posts = await db.query('SELECT * FROM posts ORDER BY created_at DESC LIMIT 10');

  return Response.json(posts);
}

// 3. Background Jobs: AWS Lambda
// lambda/process-image.ts
import { S3Event } from 'aws-lambda';
import sharp from 'sharp';

export async function handler(event: S3Event) {
  for (const record of event.Records) {
    const bucket = record.s3.bucket.name;
    const key = decodeURIComponent(record.s3.object.key);

    // Download imagen
    const image = await s3.getObject({ Bucket: bucket, Key: key });

    // Procesar con sharp
    const resized = await sharp(image.Body)
      .resize(800, 600, { fit: 'cover' })
      .webp({ quality: 80 })
      .toBuffer();

    // Upload versión procesada
    await s3.putObject({
      Bucket: bucket,
      Key: `processed/${key}`,
      Body: resized
    });
  }
}

// 4. Real-time: WebSockets serverless (Cloudflare Durable Objects)
export class ChatRoom {
  constructor(private state: DurableObjectState) {}

  async fetch(request: Request) {
    if (request.headers.get('Upgrade') === 'websocket') {
      const pair = new WebSocketPair();
      const [client, server] = Object.values(pair);

      this.handleSession(server);

      return new Response(null, {
        status: 101,
        webSocket: client
      });
    }

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

  async handleSession(websocket: WebSocket) {
    websocket.accept();

    websocket.addEventListener('message', async (event) => {
      // Broadcast para todos conectados
      this.state.getWebSockets().forEach(ws => {
        ws.send(event.data);
      });
    });
  }
}

Patrones y Buenas Prácticas

1. Cold Start Optimization

// ❌ Evita: Importaciones pesadas
import * as AWS from 'aws-sdk'; // 30MB+
import * as lodash from 'lodash'; // Toda biblioteca

export async function handler() {
  // Cold start: ~3000ms
}

// ✅ Mejor: Importaciones específicas
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import debounce from 'lodash/debounce';

export async function handler() {
  // Cold start: ~500ms
}

// ✅ Ideal: Lazy loading
export async function handler(event) {
  if (event.action === 'process-image') {
    // Importar solo cuando necesario
    const sharp = await import('sharp');
    // ...
  }
}

2. Edge Caching Strategy

// Estrategia de cache en múltiples capas
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const id = searchParams.get('id');

  // Capa 1: Edge KV (< 10ms)
  const cached = await env.KV.get(`post:${id}`);
  if (cached) {
    return new Response(cached, {
      headers: {
        'Content-Type': 'application/json',
        'X-Cache': 'HIT-EDGE'
      }
    });
  }

  // Capa 2: Database (< 50ms con Planetscale/Neon)
  const post = await db.query('SELECT * FROM posts WHERE id = ?', [id]);

  if (post) {
    // Cache en edge para próximos requests
    await env.KV.put(`post:${id}`, JSON.stringify(post), {
      expirationTtl: 3600
    });

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

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

3. Distributed Transactions

// Usar event-driven architecture
// Pub/Sub con Cloudflare Queues o AWS EventBridge

// Producer (Edge Function)
export async function POST(request: Request) {
  const order = await request.json();

  // Publicar evento en vez de procesar sincrónicamente
  await env.QUEUE.send({
    type: 'ORDER_CREATED',
    data: order
  });

  return Response.json({
    status: 'processing',
    orderId: order.id
  });
}

// Consumer (Lambda/Worker)
export async function processOrder(event) {
  const { data: order } = event;

  // Procesar de forma asíncrona
  await Promise.all([
    chargePayment(order),
    updateInventory(order),
    sendConfirmationEmail(order)
  ]);

  // Publicar evento de conclusión
  await publishEvent({
    type: 'ORDER_COMPLETED',
    orderId: order.id
  });
}

Costos: Serverless vs Tradicional

// Comparación de costo mensual
const costComparison = {
  traditional_ec2: {
    instance: 't3.medium 24/7',
    monthly_cost: '$30.40',
    load_balancer: '$16.20',
    total: '$46.60',

    traffic: '1M requests/month',
    notes: 'Pagado incluso sin uso, necesita escalar manualmente'
  },

  serverless_lambda: {
    requests: '1M requests @ $0.20/million',
    compute: '100ms avg @ $0.0000166667/GB-sec',
    monthly_cost: '$5.00',
    total: '$5.00',

    notes: 'Pagado solo por uso, escala automáticamente'
  },

  serverless_edge: {
    cloudflare_workers: {
      requests: '10M requests/month',
      bundled_plan: '$5/month',
      overage: '$0.50/million',
      total: '$5.00'
    },

    vercel_edge: {
      requests: '100k edge/month (free)',
      overage: '$20/million',
      typical_cost: '$0 - $10'
    }
  },

  savings: '~90% vs tradicional'
};

Limitaciones y Trade-offs

Limitaciones Actuales

const edgeLimitations = {
  cloudflare_workers: {
    cpu_time: '50ms free, 30s paid',
    memory: '128MB',
    bundle_size: '1MB compressed',
    no_file_system: true,
    no_native_binaries: true
  },

  vercel_edge: {
    cpu_time: '30s max',
    memory: '128MB',
    bundle_size: '1MB - 4MB',
    no_node_api: 'Limited Node.js APIs'
  },

  aws_lambda: {
    timeout: '15 minutes max',
    memory: '128MB - 10GB',
    cold_start: '~500ms - 3s',
    package_size: '250MB'
  }
};

// Cuándo NO usar edge/serverless
const notSuitableFor = [
  'WebSocket connections de larga duración',
  'Procesamiento de video pesado (> 30s)',
  'Machine Learning training',
  'Operaciones de file system complejas',
  'Conexiones database persistentes tradicionales'
];

El Futuro: 2026 y Más Allá

const futureOfServerless = {
  trends: {
    wasm_on_edge: {
      description: 'WASM corriendo en edge para performance máxima',
      players: ['Cloudflare', 'Fastly Compute@Edge', 'Vercel'],
      benefit: 'Cold start ~0ms, cualquier lenguaje'
    },

    ai_on_edge: {
      description: 'Modelos de AI corriendo en edge',
      use_cases: [
        'Image recognition',
        'Content moderation',
        'Personalization',
        'Chatbots'
      ]
    },

    edge_databases: {
      description: 'Databases distribuidas globalmente',
      examples: ['Planetscale', 'Neon', 'Turso', 'Cloudflare D1'],
      latency: '< 10ms anywhere'
    },

    serverless_gpu: {
      description: 'GPU access en funciones serverless',
      use_cases: [
        'AI inference',
        'Video processing',
        'Scientific computing'
      ]
    }
  },

  predictions: {
    '2026': 'Edge computing en 60% de las apps web',
    '2027': 'Serverless estándar para nuevos proyectos',
    '2028': 'Edge AI mainstream'
  }
};

Checklist de Migración

## Migrar para Serverless/Edge

### Análisis
- [ ] Identificar partes stateless de la aplicación
- [ ] Mapear dependencias externas
- [ ] Evaluar latency requirements
- [ ] Estimar costos (usar calculadoras de los providers)

### Preparación
- [ ] Refactorizar para funciones pequeñas y focadas
- [ ] Implementar retry logic
- [ ] Configurar monitoring (Datadog, New Relic, Sentry)
- [ ] Preparar rollback plan

### Migración Gradual
- [ ] Comenzar con endpoints de lectura (GET)
- [ ] Añadir write operations (POST/PUT)
- [ ] Migrar background jobs
- [ ] Migrar funcionalidades críticas por último

### Post-Migración
- [ ] Monitorear costos diariamente
- [ ] Optimizar cold starts
- [ ] Ajustar timeouts y memory
- [ ] Documentar arquitectura

Si estás emocionado con las arquitecturas modernas, recomiendo revisar otro artículo: React Foundation: La Nueva Era del Ecosistema React Bajo la Linux Foundation donde descubrirás cómo el ecosistema React está evolucionando para soportar estas nuevas arquitecturas.

¡Vamos a por ello! 🦅

🎯 Únete a los Desarrolladores que Están Evolucionando

Miles de desarrolladores ya usan nuestro material para acelerar sus estudios y conquistar mejores posiciones en el mercado.

¿Por qué invertir en conocimiento estructurado?

Aprender de forma organizada y con ejemplos prácticos hace toda la diferencia en tu jornada como desarrollador.

Comienza ahora:

  • $9.90 USD (pago único)

🚀 Acceder a la Guía Completa

"¡Material excelente para quien quiere profundizar!" - João, Desarrollador

Comentarios (0)

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

Añadir comentarios