Serverless y Edge Functions: Por Que 75% de las Nuevas Aplicaciones Usan Esta Arquitectura
Hola HaWkers, la forma como deployamos aplicaciones cambio drasticamente en los ultimos anos. Serverless ya no es novedad, pero Edge Functions agregaron una nueva dimension al colocar tu codigo geograficamente cerca de los usuarios. Hoy, 75% de las nuevas aplicaciones web ya nacen con algun componente serverless o edge.
Pero cuando usar cada enfoque? Cuales son los trade-offs reales? Y como JavaScript y Node.js encajan en este escenario?
El Panorama Actual
En 2025, las principales plataformas expandieron significativamente sus ofertas de edge y serverless:
Principales Players
Cloudflare Workers:
- 320+ puntos de presencia global
- Startup en < 5ms (cold start)
- Soporte a WebSockets, Durable Objects
- Precio agresivo (100k requests gratis/dia)
Vercel Edge Functions:
- Integrado con Next.js, Nuxt, SvelteKit
- Deploy automatico via Git
- Edge Middleware para routing inteligente
- Cache edge granular
AWS Lambda@Edge / CloudFront Functions:
- Integrado al ecosistema AWS
- Mayor numero de regiones
- Triggers de CDN eventos
- Escala masiva comprobada
Deno Deploy:
- TypeScript nativo
- Deploy instantaneo
- Latencia ultra baja
- Framework-agnostico
Numeros de Adopcion
Estadisticas de 2025:
- 75% de las nuevas aplicaciones web usan serverless
- 45% ya usan edge functions
- Reduccion media de 60% en latencia con edge
- Costo 40-70% menor que servidores tradicionales
Entendiendo las Diferencias
Serverless y Edge son conceptos relacionados pero distintos.
Serverless Tradicional (Lambda, Cloud Functions)
Tu codigo corre en un data center, pero no gestionas servidores:
// AWS Lambda - Handler clasico
export const handler = async (event) => {
const { body } = event;
const data = JSON.parse(body);
// Procesa los datos
const result = await processData(data);
// Guarda en DynamoDB
await dynamoDB.put({
TableName: 'orders',
Item: result
}).promise();
return {
statusCode: 200,
body: JSON.stringify({ success: true, id: result.id })
};
};Caracteristicas:
- Cold starts pueden llegar a 1-5 segundos
- Acceso a todo el ecosistema cloud (databases, queues, etc.)
- Sin limites estrictos de memoria/tiempo (configurable)
- Ideal para procesamiento pesado
Edge Functions
Tu codigo corre en puntos de presencia cerca del usuario:
// Cloudflare Workers - Edge Function
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// Logica de routing en el edge
if (url.pathname.startsWith('/api/')) {
return handleApi(request, env);
}
// Personalizacion por geolocalizacion
const country = request.cf?.country || 'US';
const content = await getLocalizedContent(country, env);
return new Response(content, {
headers: { 'Content-Type': 'text/html' }
});
}
};
async function getLocalizedContent(country: string, env: Env) {
// Busqueda del KV Storage en el edge
const cached = await env.CONTENT_KV.get(`home-${country}`);
if (cached) return cached;
// Fallback
return env.CONTENT_KV.get('home-default');
}Caracteristicas:
- Cold starts en < 50ms (generalmente < 5ms)
- Limitaciones de runtime (CPU time, memoria)
- APIs limitadas (sin filesystem, algunas Node APIs)
- Ideal para logica leve y personalizacion
Casos de Uso Practicos
Cuando Usar Edge Functions
A/B Testing y Feature Flags:
// Vercel Edge Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Determina bucket de A/B test en el edge
const bucket = request.cookies.get('ab-bucket')?.value
|| (Math.random() < 0.5 ? 'A' : 'B');
const response = NextResponse.next();
// Seta cookie si nuevo usuario
if (!request.cookies.get('ab-bucket')) {
response.cookies.set('ab-bucket', bucket, {
maxAge: 60 * 60 * 24 * 30 // 30 dias
});
}
// Rewrite para version correcta
if (bucket === 'B' && request.nextUrl.pathname === '/checkout') {
return NextResponse.rewrite(new URL('/checkout-new', request.url));
}
return response;
}
export const config = {
matcher: ['/checkout', '/product/:path*']
};Autenticacion y Proteccion:
// Validacion de JWT en el edge
import { jwtVerify } from 'jose';
export default {
async fetch(request: Request, env: Env) {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return new Response('Unauthorized', { status: 401 });
}
try {
const secret = new TextEncoder().encode(env.JWT_SECRET);
const { payload } = await jwtVerify(token, secret);
// Agrega user info al request
const newHeaders = new Headers(request.headers);
newHeaders.set('X-User-Id', payload.sub as string);
return fetch(request, { headers: newHeaders });
} catch {
return new Response('Invalid token', { status: 401 });
}
}
};
Cuando Usar Serverless Tradicional
Procesamiento Pesado:
// AWS Lambda para procesamiento de imagen
import sharp from 'sharp';
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
export const handler = async (event) => {
const { bucket, key } = event;
// Busca imagen original
const s3 = new S3Client({});
const original = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
// Procesa con Sharp (no disponible en el edge)
const processed = await sharp(await original.Body.transformToByteArray())
.resize(800, 600, { fit: 'inside' })
.webp({ quality: 80 })
.toBuffer();
// Guarda version optimizada
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: key.replace(/\.\w+$/, '.webp'),
Body: processed,
ContentType: 'image/webp'
}));
return { processed: true };
};Integracion con Databases:
// Lambda con conexion a banco
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 10
});
export const handler = async (event) => {
const { userId, action, data } = JSON.parse(event.body);
const client = await pool.connect();
try {
await client.query('BEGIN');
// Transaccion compleja
const result = await client.query(
'INSERT INTO orders (user_id, data) VALUES ($1, $2) RETURNING id',
[userId, data]
);
await client.query(
'UPDATE users SET last_order = NOW() WHERE id = $1',
[userId]
);
await client.query('COMMIT');
return {
statusCode: 200,
body: JSON.stringify({ orderId: result.rows[0].id })
};
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
};
Arquitectura Hibrida
El enfoque mas comun en 2025 es combinar edge y serverless:
Patron Recomendado
Usuario
|
v
[Edge Function] ─────────────────┐
│ │
│ - Auth validation │
│ - A/B testing │
│ - Geo routing │
│ - Cache check │
│ │
v v
[CDN Cache] <──── o ────> [Origin/Lambda]
│ │
│ - Static assets │ - Business logic
│ - Cached responses │ - Database ops
│ │ - Heavy processing
v v
[Usuario] [Database/Storage]Ejemplo con Next.js
// middleware.ts (Edge)
export function middleware(request: NextRequest) {
// Logica leve en el edge
const country = request.geo?.country || 'US';
const response = NextResponse.next();
response.headers.set('X-Country', country);
return response;
}
// app/api/orders/route.ts (Serverless)
export async function POST(request: Request) {
// Logica pesada en serverless
const data = await request.json();
const order = await prisma.order.create({
data: {
...data,
country: request.headers.get('X-Country')
}
});
return Response.json(order);
}
Trade-offs y Consideraciones
Limitaciones del Edge
Restricciones comunes:
- CPU time limitado (generalmente 50-100ms)
- Memoria limitada (128MB tipico)
- Sin acceso a filesystem
- Subset de APIs Node.js
- Conexiones de banco mas complejas
Cuando NO Usar Edge
Evita edge para:
- Queries complejas de banco
- Procesamiento de archivos grandes
- Operaciones que llevan > 100ms
- Dependencias Node.js pesadas (sharp, puppeteer)
Costos
| Enfoque | Costo Tipico | Cold Start | Latencia |
|---|---|---|---|
| Edge Function | $0.50/millon req | < 5ms | 10-50ms |
| Lambda | $0.20/millon req | 100-5000ms | 50-200ms |
| Container | $50-200/mes | 0ms | 20-100ms |
Conclusion
Serverless y Edge Functions no son enfoques exclusivos, sino complementarios. Edge es ideal para logica leve, personalizacion y reduccion de latencia. Serverless tradicional continua siendo la mejor opcion para procesamiento pesado e integracion con databases.
En 2025, la mayoria de las aplicaciones bien arquitectadas usa ambos: edge para la primera capa de procesamiento y serverless para operaciones mas complejas.
Si quieres entender mas sobre arquitecturas modernas de JavaScript, recomiendo conferir el articulo sobre Async/Await en JavaScript donde exploramos patrones que funcionan bien en estas arquitecturas.

