Serverless y Edge Computing: Arquitectura de Baja Latencia que Domina 2025
Hola HaWkers, ¿recuerdas cuando deployar una aplicación significaba provisionar servidores, configurar balanceadores de carga, gestionar escalabilidad manualmente y rezar para que el tráfico no derribara todo? Pues bien, esos días parecen cada vez más distantes.
En 2025, la combinación de serverless y edge computing transformó completamente cómo pensamos en infraestructura. Hoy, puedes escribir una función, hacer deploy, y estará corriendo en más de 300 localidades alrededor del mundo, respondiendo en menos de 50ms, escalando automáticamente de 0 a millones de solicitudes - todo sin gestionar un solo servidor.
¿Parece magia? Vamos a descubrir cómo funciona esta arquitectura en la práctica.
Serverless: Más Allá del Hype, La Realidad Práctica
Serverless no significa "sin servidores" - significa que tú no necesitas preocuparte con servidores. La infraestructura está abstraída, pagas solo por lo que usas, y la escala ocurre automáticamente.
El Modelo de Ejecución Serverless
Diferente de servidores tradicionales que corren 24/7, funciones serverless son event-driven:
- Cold Start: Primera invocación inicializa el ambiente de ejecución
- Warm: Ejecuciones subsecuentes reaprovechan el ambiente (si dentro de la ventana de tiempo)
- Scaling: Múltiples instancias son creadas automáticamente bajo demanda
- Billing: Pagas solo por el tiempo de ejecución (milisegundos)
Cuándo Serverless Realmente Brilla
APIs con Tráfico Irregular: Si tu API tiene picos de uso (e-commerce en Black Friday, por ejemplo), serverless escala automáticamente.
Procesamiento de Eventos: Procesamiento de imágenes, webhooks, jobs programados - perfectos para serverless.
Backends para JAMstack: Next.js, Nuxt, Remix - todos usan serverless functions para API routes.
Microservicios Ligeros: Cada función puede ser un microservicio independiente, deployado separadamente.
Edge Computing: Llevando Código Cerca del Usuario
Edge computing lleva serverless un paso más allá: en vez de correr en una región específica (us-east-1, por ejemplo), tu código corre en data centers esparcidos globalmente, próximos a tus usuarios.
Un usuario en Ciudad de México accede al edge node mexicano. Un usuario en Tokio accede al edge node japonés. Misma aplicación, latencia drásticamente reducida.
La Diferencia Entre Serverless Tradicional y Edge
AWS Lambda (Serverless Regional):
- Ejecuta en una región específica (ej: us-east-1)
- Cold start: 100-500ms
- Latencia adicional para usuarios distantes
Cloudflare Workers (Edge Computing):
- Ejecuta en 300+ localidades globalmente
- Cold start: <10ms
- Latencia consistentemente baja globalmente
Casos de Uso Ideales Para Edge
Personalización de Contenido: Modificar HTML basado en geolocalización, A/B testing, feature flags.
Autenticación y Autorización: Verificar tokens JWT antes de que requests lleguen al backend.
API Gateways: Enrutamiento inteligente, rate limiting, caching.
Middleware de Solicitudes: Headers, redirects, rewrite de URLs.
Cloudflare Workers: Edge Computing en la Práctica
Cloudflare Workers es la plataforma de edge computing más popular en 2025. Veamos un ejemplo práctico:
Ejemplo 1: API de Geolocalización con Cache Inteligente
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Información de geolocalización disponible automáticamente
const country = request.cf.country;
const city = request.cf.city;
const timezone = request.cf.timezone;
// Cache key basado en localización
const cacheKey = `geo:${country}:${city}`;
// Verificar cache en KV (key-value store de Cloudflare)
let data = await env.GEO_CACHE.get(cacheKey, { type: 'json' });
if (!data) {
// Buscar datos customizados para esa localización
data = await fetchLocationData(country, city);
// Cachear por 1 hora
await env.GEO_CACHE.put(cacheKey, JSON.stringify(data), {
expirationTtl: 3600,
});
}
return new Response(JSON.stringify({
location: { country, city, timezone },
data,
cached: !!data,
}), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=3600',
},
});
},
};
async function fetchLocationData(country, city) {
// Simular búsqueda de datos personalizados
return {
currency: getCurrencyForCountry(country),
language: getLanguageForCountry(country),
popularProducts: await getPopularProducts(country),
shippingOptions: await getShippingOptions(city),
};
}
function getCurrencyForCountry(country) {
const currencies = {
BR: 'BRL',
US: 'USD',
JP: 'JPY',
GB: 'GBP',
MX: 'MXN',
ES: 'EUR',
};
return currencies[country] || 'USD';
}Este worker corre en el edge más próximo al usuario, detecta automáticamente la localización, y retorna datos personalizados con latencia mínima.
Ejemplo 2: Autenticación JWT en el Edge
import { verify } from '@tsndr/cloudflare-worker-jwt';
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Rutas públicas no requieren auth
const publicRoutes = ['/health', '/login', '/register'];
if (publicRoutes.includes(url.pathname)) {
return fetch(request);
}
// Extraer token del header
const authHeader = request.headers.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.substring(7);
try {
// Verificar JWT en el edge (¡sin llamar al backend!)
const isValid = await verify(token, env.JWT_SECRET);
if (!isValid) {
return new Response('Invalid token', { status: 401 });
}
// Decodificar payload para añadir al request
const { payload } = jwt.decode(token);
// Clonar request y añadir user info en los headers
const modifiedRequest = new Request(request);
modifiedRequest.headers.set('X-User-Id', payload.userId);
modifiedRequest.headers.set('X-User-Role', payload.role);
// Encaminar para origin
return fetch(modifiedRequest);
} catch (error) {
return new Response('Token verification failed', { status: 401 });
}
},
};Este enfoque verifica autenticación en el edge, antes de que la solicitud llegue a tu backend, economizando latencia y carga en los servidores.
AWS Lambda@Edge: Serverless en la CDN de Amazon
AWS Lambda@Edge permite correr funciones Lambda en los edge locations de CloudFront (200+ localizaciones).
Ejemplo: Redirección Inteligente Basada en Device
// Lambda@Edge para CloudFront
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
// Detectar tipo de device
const userAgent = headers['user-agent']?.[0]?.value || '';
const isMobile = /mobile|android|iphone/i.test(userAgent);
const isTablet = /tablet|ipad/i.test(userAgent);
// Redirigir para versiones optimizadas
if (request.uri === '/') {
if (isMobile) {
return {
status: '302',
statusDescription: 'Found',
headers: {
location: [{
key: 'Location',
value: '/mobile',
}],
},
};
}
if (isTablet) {
return {
status: '302',
statusDescription: 'Found',
headers: {
location: [{
key: 'Location',
value: '/tablet',
}],
},
};
}
}
// Modificar headers para optimización
request.headers['x-device-type'] = [{
key: 'X-Device-Type',
value: isMobile ? 'mobile' : isTablet ? 'tablet' : 'desktop',
}];
return request;
};Ejemplo: Generación de Imágenes Responsivas en el Edge
const sharp = require('sharp');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
// Extraer parámetros de query
const params = new URLSearchParams(request.querystring);
const width = parseInt(params.get('w') || '800');
const quality = parseInt(params.get('q') || '80');
const format = params.get('f') || 'webp';
// Buscar imagen original del S3
const s3Object = await s3.getObject({
Bucket: 'my-images-bucket',
Key: request.uri.substring(1), // remueve leading /
}).promise();
// Procesar imagen con Sharp
const processedImage = await sharp(s3Object.Body)
.resize(width, null, { withoutEnlargement: true })
.toFormat(format, { quality })
.toBuffer();
// Retornar imagen procesada
return {
status: '200',
statusDescription: 'OK',
headers: {
'content-type': [{
key: 'Content-Type',
value: `image/${format}`,
}],
'cache-control': [{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
}],
},
body: processedImage.toString('base64'),
bodyEncoding: 'base64',
};
};
Vercel Edge Functions: Next.js en el Edge
Vercel Edge Functions son optimizadas para Next.js y corren en el edge globalmente.
Ejemplo: A/B Testing en el Edge
// app/middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// Bucket aleatorio para A/B test (0-99)
const bucket = Math.floor(Math.random() * 100);
// 50% de los usuarios ven variante A, 50% ven B
const variant = bucket < 50 ? 'A' : 'B';
// Clonar response para añadir cookie
const response = NextResponse.next();
// Almacenar variante en cookie (persistencia entre páginas)
response.cookies.set('ab-test-variant', variant, {
maxAge: 60 * 60 * 24 * 30, // 30 días
});
// Añadir header para analytics
response.headers.set('X-AB-Test-Variant', variant);
// Rewrite basado en la variante
if (request.nextUrl.pathname === '/pricing') {
if (variant === 'B') {
return NextResponse.rewrite(new URL('/pricing-variant-b', request.url));
}
}
return response;
}
export const config = {
matcher: ['/pricing', '/checkout'],
};Ejemplo: Rate Limiting en el Edge
import { NextResponse } from 'next/server';
const rateLimit = new Map();
export function middleware(request) {
const ip = request.ip || 'unknown';
const now = Date.now();
const windowMs = 60 * 1000; // 1 minuto
const maxRequests = 100;
// Limpiar entradas antiguas
for (const [key, value] of rateLimit.entries()) {
if (now - value.timestamp > windowMs) {
rateLimit.delete(key);
}
}
// Verificar rate limit
const userLimit = rateLimit.get(ip);
if (!userLimit) {
rateLimit.set(ip, { count: 1, timestamp: now });
} else if (now - userLimit.timestamp > windowMs) {
// Resetar ventana
rateLimit.set(ip, { count: 1, timestamp: now });
} else if (userLimit.count >= maxRequests) {
// Límite excedido
return new NextResponse('Rate limit exceeded', {
status: 429,
headers: {
'Retry-After': String(Math.ceil((windowMs - (now - userLimit.timestamp)) / 1000)),
},
});
} else {
// Incrementar contador
userLimit.count++;
}
return NextResponse.next();
}
Patrones de Arquitectura Serverless Moderna
1. Backend for Frontend (BFF) Pattern
// Cloudflare Worker actuando como BFF
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Diferentes backends para diferentes clientes
if (url.pathname.startsWith('/api/mobile')) {
// Mobile recibe datos optimizados (menos campos)
const data = await fetchFromBackend(env.MOBILE_API);
return new Response(JSON.stringify({
...data,
_optimized: true,
}));
}
if (url.pathname.startsWith('/api/web')) {
// Web recibe datos completos
const data = await fetchFromBackend(env.WEB_API);
return new Response(JSON.stringify(data));
}
return new Response('Not Found', { status: 404 });
},
};2. Event-Driven Serverless
// AWS Lambda triggered por S3 upload
exports.handler = async (event) => {
const s3Event = event.Records[0].s3;
const bucket = s3Event.bucket.name;
const key = s3Event.object.key;
console.log(`Processing file: ${key} from bucket: ${bucket}`);
// Procesar imagen
const originalImage = await s3.getObject({ Bucket: bucket, Key: key }).promise();
// Generar thumbnails en paralelo
const thumbnails = await Promise.all([
generateThumbnail(originalImage, 200, 200),
generateThumbnail(originalImage, 400, 400),
generateThumbnail(originalImage, 800, 800),
]);
// Upload thumbnails para S3
await Promise.all(thumbnails.map((thumb, i) =>
s3.putObject({
Bucket: `${bucket}-thumbnails`,
Key: `${key}-${[200, 400, 800][i]}px`,
Body: thumb,
ContentType: 'image/jpeg',
}).promise()
));
return { statusCode: 200, body: 'Thumbnails generated' };
};3. Caching Estratégico en el Edge
export default {
async fetch(request, env, ctx) {
const cache = caches.default;
const cacheKey = new Request(request.url, request);
// Verificar cache primero
let response = await cache.match(cacheKey);
if (!response) {
// Cache miss - buscar del backend
response = await fetch(request);
// Cachear si status es 200
if (response.status === 200) {
// Clonar response para cachear (puede ser consumida solo 1x)
const responseToCache = response.clone();
// Añadir al cache (asíncrono via waitUntil)
ctx.waitUntil(cache.put(cacheKey, responseToCache));
}
}
return response;
},
};
Desafíos y Consideraciones Prácticas
Cold Starts: El Talón de Aquiles
Funciones serverless sufren de "cold starts" cuando quedan inactivas. Estrategias para mitigar:
1. Keep-Alive Pings: Invocar funciones periódicamente para mantenerlas warm
2. Provisioned Concurrency (AWS): Mantener instancias siempre warm (costo adicional)
3. Edge Computing: Workers tienen cold starts drásticamente menores (<10ms)
Límites de Ejecución
AWS Lambda: 15 minutos máximo
Cloudflare Workers: 50ms CPU time (plan free), 50ms-30s (plan pago)
Vercel Edge: 30 segundos
Para procesamientos largos, considera split en múltiples funciones o usar Step Functions.
Monitoreo y Debugging
Serverless dificulta debugging tradicional. Usa:
- Structured Logging: JSON logs para fácil parsing
- Distributed Tracing: AWS X-Ray, Datadog, Sentry
- Metrics: CloudWatch, Prometheus para monitorear latencia y errores
El Futuro: Edge-First Architecture
En 2025, la tendencia es clara: edge-first. Aplicaciones modernas están siendo diseñadas desde el inicio para correr en el edge, aprovechando:
- Baja latencia global: Usuarios en México y Japón tienen la misma experiencia
- Escalabilidad automática: De 0 a millones sin configuración
- Costo optimizado: Paga solo por lo que usas
- Resiliencia: Distribuido globalmente, sin single point of failure
Si estás construyendo aplicaciones web modernas, serverless y edge computing ya no son "nice to have" - son esenciales para competir en performance y experiencia del usuario.
Si te sientes inspirado por el poder del serverless y edge computing, te recomiendo echar un vistazo a otro artículo: Microfrontends: Arquitectura Modular donde descubrirás cómo combinar edge computing con arquitectura de microfrontends para crear aplicaciones verdaderamente escalables.
¡Vamos a por ello! 🦅
📚 ¿Quieres Profundizar Tus Conocimientos en JavaScript?
Este artículo cubrió serverless y edge computing, pero hay mucho más por explorar en el mundo del desarrollo moderno.
Desarrolladores que invierten en conocimiento sólido y estructurado tienden a tener más oportunidades en el mercado.
Material de Estudio Completo
Si quieres dominar JavaScript de básico a avanzado, preparé una guía completa:
Opciones de inversión:
- $9.90 USD (pago único)
💡 Material actualizado con las mejores prácticas del mercado

