Serverless e Edge Functions: Por Que 75% das Novas Aplicacoes Usam Essa Arquitetura
Ola HaWkers, a forma como deployamos aplicacoes mudou drasticamente nos ultimos anos. Serverless ja nao e mais novidade, mas Edge Functions adicionaram uma nova dimensao ao colocar seu codigo geograficamente proximo aos usuarios. Hoje, 75% das novas aplicacoes web ja nascem com algum componente serverless ou edge.
Mas quando usar cada abordagem? Quais sao os trade-offs reais? E como JavaScript e Node.js se encaixam nesse cenario?
O Panorama Atual
Em 2025, as principais plataformas expandiram significativamente suas ofertas de edge e serverless:
Principais Players
Cloudflare Workers:
- 320+ pontos de presenca global
- Startup em < 5ms (cold start)
- Suporte a WebSockets, Durable Objects
- Preco agressivo (100k requests gratis/dia)
Vercel Edge Functions:
- Integrado com Next.js, Nuxt, SvelteKit
- Deploy automatico via Git
- Edge Middleware para routing inteligente
- Cache edge granular
AWS Lambda@Edge / CloudFront Functions:
- Integrado ao ecossistema AWS
- Maior numero de regioes
- Triggers de CDN eventos
- Escala massiva comprovada
Deno Deploy:
- TypeScript nativo
- Deploy instantaneo
- Latencia ultra baixa
- Framework-agnostico
Numeros de Adocao
Estatisticas de 2025:
- 75% das novas aplicacoes web usam serverless
- 45% ja usam edge functions
- Reducao media de 60% em latencia com edge
- Custo 40-70% menor que servidores tradicionais
Entendendo as Diferencas
Serverless e Edge sao conceitos relacionados mas distintos.
Serverless Tradicional (Lambda, Cloud Functions)
Seu codigo roda em um data center, mas voce nao gerencia servidores:
// AWS Lambda - Handler classico
export const handler = async (event) => {
const { body } = event;
const data = JSON.parse(body);
// Processa os dados
const result = await processData(data);
// Salva no DynamoDB
await dynamoDB.put({
TableName: 'orders',
Item: result
}).promise();
return {
statusCode: 200,
body: JSON.stringify({ success: true, id: result.id })
};
};Caracteristicas:
- Cold starts podem chegar a 1-5 segundos
- Acesso a todo o ecossistema cloud (databases, queues, etc.)
- Sem limites estritos de memoria/tempo (configuravel)
- Ideal para processamento pesado
Edge Functions
Seu codigo roda em pontos de presenca proximos ao usuario:
// Cloudflare Workers - Edge Function
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// Logica de routing no edge
if (url.pathname.startsWith('/api/')) {
return handleApi(request, env);
}
// Personalizacao por geolocalizacao
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) {
// Busca do KV Storage no 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 em < 50ms (geralmente < 5ms)
- Limitacoes de runtime (CPU time, memoria)
- APIs limitadas (sem filesystem, algumas Node APIs)
- Ideal para logica leve e personalizacao
Casos de Uso Praticos
Quando Usar Edge Functions
A/B Testing e 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 no edge
const bucket = request.cookies.get('ab-bucket')?.value
|| (Math.random() < 0.5 ? 'A' : 'B');
const response = NextResponse.next();
// Seta cookie se novo usuario
if (!request.cookies.get('ab-bucket')) {
response.cookies.set('ab-bucket', bucket, {
maxAge: 60 * 60 * 24 * 30 // 30 dias
});
}
// Rewrite para versao correta
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*']
};Autenticacao e Protecao:
// Validacao de JWT no 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);
// Adiciona user info ao 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 });
}
}
};
Quando Usar Serverless Tradicional
Processamento Pesado:
// AWS Lambda para processamento de imagem
import sharp from 'sharp';
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
export const handler = async (event) => {
const { bucket, key } = event;
// Busca imagem original
const s3 = new S3Client({});
const original = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
// Processa com Sharp (nao disponivel no edge)
const processed = await sharp(await original.Body.transformToByteArray())
.resize(800, 600, { fit: 'inside' })
.webp({ quality: 80 })
.toBuffer();
// Salva versao otimizada
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: key.replace(/\.\w+$/, '.webp'),
Body: processed,
ContentType: 'image/webp'
}));
return { processed: true };
};Integracao com Databases:
// Lambda com conexao 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');
// Transacao complexa
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();
}
};
Arquitetura Hibrida
A abordagem mais comum em 2025 e combinar edge e serverless:
Padrao Recomendado
Usuario
|
v
[Edge Function] ─────────────────┐
│ │
│ - Auth validation │
│ - A/B testing │
│ - Geo routing │
│ - Cache check │
│ │
v v
[CDN Cache] <──── ou ────> [Origin/Lambda]
│ │
│ - Static assets │ - Business logic
│ - Cached responses │ - Database ops
│ │ - Heavy processing
v v
[Usuario] [Database/Storage]Exemplo com Next.js
// middleware.ts (Edge)
export function middleware(request: NextRequest) {
// Logica leve no 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 no 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 e Consideracoes
Limitacoes do Edge
Restricoes comuns:
- CPU time limitado (geralmente 50-100ms)
- Memoria limitada (128MB tipico)
- Sem acesso a filesystem
- Subset de APIs Node.js
- Conexoes de banco mais complexas
Quando NAO Usar Edge
Evite edge para:
- Queries complexas de banco
- Processamento de arquivos grandes
- Operacoes que levam > 100ms
- Dependencias Node.js pesadas (sharp, puppeteer)
Custos
| Abordagem | Custo Tipico | Cold Start | Latencia |
|---|---|---|---|
| Edge Function | $0.50/milhao req | < 5ms | 10-50ms |
| Lambda | $0.20/milhao req | 100-5000ms | 50-200ms |
| Container | $50-200/mes | 0ms | 20-100ms |
Conclusao
Serverless e Edge Functions nao sao abordagens exclusivas, mas complementares. Edge e ideal para logica leve, personalizacao e reducao de latencia. Serverless tradicional continua sendo a melhor opcao para processamento pesado e integracao com databases.
Em 2025, a maioria das aplicacoes bem arquitetadas usa ambos: edge para a primeira camada de processamento e serverless para operacoes mais complexas.
Se voce quer entender mais sobre arquiteturas modernas de JavaScript, recomendo conferir o artigo sobre Async/Await no JavaScript onde exploramos padroes que funcionam bem nessas arquiteturas.

