Edge Functions y el Futuro del Serverless: Arquitectura Moderna en 2025
Hola HaWkers, el mundo serverless evolucionó significativamente en los últimos años, y 2025 marca la consolidación de las Edge Functions como estándar para aplicaciones de alta performance. Si aún no estás familiarizado con edge computing o quieres entender cómo aprovechar esa tecnología, este artículo te guiará por los conceptos y prácticas más importantes.
¿Qué exactamente son Edge Functions? ¿Por qué ofrecen performance superior a las funciones serverless tradicionales? ¿Y cómo puedes implementarlas en tus proyectos? Vamos a explorar todo esto con ejemplos prácticos.
Qué Son Edge Functions
Edge Functions son funciones serverless que ejecutan en servidores distribuidos geográficamente, próximos a los usuarios finales. Diferente de funciones tradicionales que corren en regiones específicas, edge computing lleva la computación para el borde de la red.
Diferencia Entre Serverless Tradicional y Edge
Serverless Tradicional:
- Ejecuta en regiones específicas (us-east-1, eu-west-1, etc.)
- Latencia depende de la distancia del usuario al datacenter
- Cold start puede ser significativo (centenas de ms a segundos)
- Ambiente Node.js completo generalmente disponible
Edge Functions:
- Ejecutan en centenas de puntos de presencia globales
- Latencia consistentemente baja independiente de la localización
- Cold start mínimo (pocos milisegundos)
- Runtime optimizado basado en V8 o similar
💡 Contexto: Para un usuario en España accediendo una función en us-east-1, la latencia de red puede ser 100-200ms. Con edge, esa latencia cae para 10-30ms.
Por Qué Edge Functions Dominan en 2025
La adopción de edge functions creció exponencialmente por varias razones:
1. Performance Global
Con servidores en más de 300 locales alrededor del mundo, usuarios de cualquier lugar tienen latencia similar y baja.
2. Costo-Beneficio
A pesar del costo por ejecución similar, la menor latencia significa menos tiempo de espera y mejor experiencia, justificando la inversión.
3. Casos de Uso Expandidos
Inicialmente usadas solo para redirecciones simples, ahora soportan:
Casos de uso modernos:
- Autenticación y autorización
- Personalización de contenido
- A/B testing
- Rate limiting
- Manipulación de headers
- Renderización server-side
- APIs completas
4. Ecosistema Maduro
Plataformas como Cloudflare Workers, Vercel Edge Functions, Deno Deploy y AWS CloudFront Functions maduraron significativamente.
Implementando Edge Functions en la Práctica
Vamos a ver ejemplos prácticos usando diferentes plataformas.
Vercel Edge Functions
Perfectas para proyectos Next.js:
// pages/api/geo.ts o app/api/geo/route.ts
import { NextRequest, NextResponse } from 'next/server';
export const config = {
runtime: 'edge', // Define que es edge function
};
export default function handler(req: NextRequest) {
// Informaciones de geolocalización disponibles automáticamente
const country = req.geo?.country ?? 'Desconocido';
const city = req.geo?.city ?? 'Desconocida';
const region = req.geo?.region ?? 'Desconocida';
return NextResponse.json({
message: `¡Hola visitante de ${city}, ${region}, ${country}!`,
latency: 'Esta respuesta vino del edge más próximo a ti',
timestamp: new Date().toISOString(),
});
}Cloudflare Workers
Una de las plataformas más populares para edge:
// worker.ts
export interface Env {
MY_KV: KVNamespace;
}
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
const url = new URL(request.url);
// Rate limiting simple usando KV
const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown';
const rateLimitKey = `ratelimit:${ip}`;
const currentCount = await env.MY_KV.get(rateLimitKey);
const count = currentCount ? parseInt(currentCount) : 0;
if (count > 100) {
return new Response('Rate limit exceeded', { status: 429 });
}
// Incrementa contador con TTL de 1 minuto
ctx.waitUntil(
env.MY_KV.put(rateLimitKey, String(count + 1), {
expirationTtl: 60
})
);
// Lógica principal
if (url.pathname === '/api/data') {
const data = await fetchDataFromOrigin();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}
return new Response('Not Found', { status: 404 });
},
};
async function fetchDataFromOrigin() {
// Simula búsqueda de datos
return { message: 'Datos del edge', timestamp: Date.now() };
}
Deno Deploy
Plataforma nativa para edge con Deno:
// server.ts
import { serve } from 'https://deno.land/std/http/server.ts';
interface RequestInfo {
method: string;
url: string;
userAgent: string | null;
region: string | null;
}
serve(async (request: Request): Promise<Response> => {
const requestInfo: RequestInfo = {
method: request.method,
url: request.url,
userAgent: request.headers.get('user-agent'),
region: Deno.env.get('DENO_REGION') ?? 'unknown',
};
// Ruteo simple
const url = new URL(request.url);
switch (url.pathname) {
case '/':
return new Response('Hello from Deno Edge!', {
headers: { 'content-type': 'text/plain' },
});
case '/api/info':
return new Response(JSON.stringify(requestInfo), {
headers: { 'content-type': 'application/json' },
});
case '/api/time':
const now = new Date();
return new Response(
JSON.stringify({
utc: now.toUTCString(),
iso: now.toISOString(),
region: requestInfo.region,
}),
{ headers: { 'content-type': 'application/json' } }
);
default:
return new Response('Not Found', { status: 404 });
}
});
Patrones Avanzados con Edge Functions
Middleware de Autenticación
// middleware.ts (Next.js Edge Middleware)
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify } from 'jose';
const PUBLIC_PATHS = ['/', '/login', '/api/auth'];
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Permite rutas públicas
if (PUBLIC_PATHS.some(path => pathname.startsWith(path))) {
return NextResponse.next();
}
// Verifica token JWT
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
try {
const { payload } = await jwtVerify(token, JWT_SECRET);
// Añade info del usuario a los headers
const response = NextResponse.next();
response.headers.set('x-user-id', payload.sub as string);
response.headers.set('x-user-role', payload.role as string);
return response;
} catch (error) {
// Token inválido
const response = NextResponse.redirect(new URL('/login', request.url));
response.cookies.delete('auth-token');
return response;
}
}
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico).*)',
],
};A/B Testing en el Edge
// Cloudflare Worker para A/B testing
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Verifica cookie existente o atribuye variante
const cookies = request.headers.get('Cookie') ?? '';
let variant = getCookie(cookies, 'ab-variant');
if (!variant) {
// Atribuye variante aleatoriamente (50/50)
variant = Math.random() < 0.5 ? 'A' : 'B';
}
// Modifica respuesta basado en la variante
const response = await fetch(request);
const html = await response.text();
let modifiedHtml = html;
if (variant === 'B') {
// Aplica cambios de la variante B
modifiedHtml = html.replace(
'<button class="cta">Comprar Ahora</button>',
'<button class="cta-new">Añadir al Carrito</button>'
);
}
const newResponse = new Response(modifiedHtml, response);
// Define cookie para mantener consistencia
newResponse.headers.append(
'Set-Cookie',
`ab-variant=${variant}; Path=/; Max-Age=604800`
);
return newResponse;
},
};
function getCookie(cookies: string, name: string): string | null {
const match = cookies.match(new RegExp(`${name}=([^;]+)`));
return match ? match[1] : null;
}
Limitaciones y Consideraciones
Qué Edge Functions No Hacen Bien
Limitaciones importantes:
- Tiempo de ejecución limitado (generalmente 30s máximo, algunos 50ms)
- Memoria restringida (128MB típico)
- Sin acceso a filesystem
- APIs limitadas (sin Node.js nativo completo)
- Conexiones de larga duración problemáticas
Cuándo Usar Serverless Tradicional
Prefiere serverless tradicional para:
- Procesamiento intensivo de CPU
- Operaciones de base de datos complejas
- Tareas de larga duración
- Cuando necesitas ecosistema Node.js completo
- Procesamiento de archivos grandes
Arquitectura Híbrida
El mejor abordaje generalmente combina edge y serverless:
Usuario
↓
Edge Function (autenticación, cache, personalización)
↓
Serverless Function (lógica de negocio, base de datos)
↓
Base de Datos / Servicios
Comparativo de Plataformas
| Plataforma | Cold Start | Locales | Lenguajes | Uso Gratuito |
|---|---|---|---|---|
| Cloudflare Workers | ~0ms | 300+ | JS/TS, Rust, WASM | 100k req/día |
| Vercel Edge | ~1ms | 100+ | JS/TS | Conforme plan |
| Deno Deploy | ~1ms | 35+ | JS/TS, WASM | 1M req/mes |
| AWS CloudFront | ~5ms | 400+ | JS | Conforme uso |
| Fastly Compute | ~5ms | 70+ | JS, Rust, WASM | Conforme uso |
Eligiendo la Plataforma Correcta
Cloudflare Workers:
- Mejor para aplicaciones standalone
- Ecosistema más maduro (KV, D1, R2)
- Precios competitivos
Vercel Edge:
- Ideal para proyectos Next.js
- Integración perfecta con framework
- Edge Middleware poderoso
Deno Deploy:
- Óptimo para quien prefiere Deno
- Deploy vía GitHub simple
- TypeScript first-class
Mejores Prácticas
1. Cache Agresivo
// Implementa cache para respuestas que pueden ser cacheadas
export default {
async fetch(request: Request): Promise<Response> {
const cacheKey = new Request(request.url, request);
const cache = caches.default;
// Verifica cache primero
let response = await cache.match(cacheKey);
if (!response) {
response = await fetch(request);
// Clone para cachear
response = new Response(response.body, response);
response.headers.set('Cache-Control', 'public, max-age=3600');
// Cache en background
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
return response;
},
};2. Tratamiento de Errores Robusto
export default {
async fetch(request: Request): Promise<Response> {
try {
return await handleRequest(request);
} catch (error) {
console.error('Edge function error:', error);
// Retorna respuesta de error amigable
return new Response(
JSON.stringify({
error: 'Internal Error',
message: 'Something went wrong',
}),
{
status: 500,
headers: { 'Content-Type': 'application/json' },
}
);
}
},
};3. Monitoreo y Observabilidad
// Añade logging estructurado
interface LogEntry {
timestamp: string;
level: 'info' | 'warn' | 'error';
message: string;
metadata?: Record<string, unknown>;
}
function log(entry: LogEntry) {
console.log(JSON.stringify(entry));
}
export default {
async fetch(request: Request): Promise<Response> {
const startTime = Date.now();
const response = await handleRequest(request);
log({
timestamp: new Date().toISOString(),
level: 'info',
message: 'Request handled',
metadata: {
url: request.url,
method: request.method,
status: response.status,
duration: Date.now() - startTime,
},
});
return response;
},
};
Conclusión
Edge Functions representan una evolución significativa en la arquitectura serverless, ofreciendo latencia consistentemente baja para usuarios globales. En 2025, se tornaron componente esencial para aplicaciones que priorizan performance.
La clave es entender cuándo usar edge versus serverless tradicional. Para autenticación, personalización, rate limiting y respuestas rápidas, edge es ideal. Para procesamiento pesado y lógica compleja de negocio, serverless tradicional continúa siendo la elección correcta.
La combinación de ambos ofrece lo mejor de los dos mundos: respuestas rápidas en el edge con poder de procesamiento en el backend cuando necesario.
Si quieres profundizarte en arquitecturas modernas, recomiendo que revises otro artículo: Waymo Suspende Robotaxis en San Francisco donde vas a descubrir cómo construir experiencias web modernas y performáticas.

