Serverless e Edge Computing: Arquitetura de Baixa Latência que Domina 2025
Olá HaWkers, lembra quando deployar uma aplicação significava provisionar servidores, configurar balanceadores de carga, gerenciar escalabilidade manualmente e orar para que o tráfego não derrubasse tudo? Pois é, esses dias parecem cada vez mais distantes.
Em 2025, a combinação de serverless e edge computing transformou completamente como pensamos em infraestrutura. Hoje, você pode escrever uma função, dar deploy, e ela estará rodando em mais de 300 localidades ao redor do mundo, respondendo em menos de 50ms, escalando automaticamente de 0 a milhões de requisições - tudo sem você gerenciar um único servidor.
Parece mágica? Vamos desvendar como essa arquitetura funciona na prática.
Serverless: Além do Hype, A Realidade Prática
Serverless não significa "sem servidores" - significa que você não precisa se preocupar com servidores. A infraestrutura é abstraída, você paga apenas pelo que usa, e a escala acontece automaticamente.
O Modelo de Execução Serverless
Diferente de servidores tradicionais que ficam rodando 24/7, funções serverless são event-driven:
- Cold Start: Primeira invocação inicializa o ambiente de execução
- Warm: Execuções subsequentes reaproveitam o ambiente (se dentro da janela de tempo)
- Scaling: Múltiplas instâncias são criadas automaticamente sob demanda
- Billing: Você paga apenas pelo tempo de execução (milissegundos)
Quando Serverless Realmente Brilha
APIs com Tráfego Irregular: Se sua API tem picos de uso (e-commerce na Black Friday, por exemplo), serverless escala automaticamente.
Processamento de Eventos: Processamento de imagens, webhooks, jobs agendados - perfeitos para serverless.
Backends para JAMstack: Next.js, Nuxt, Remix - todos usam serverless functions para API routes.
Microserviços Leves: Cada função pode ser um microserviço independente, deployado separadamente.
Edge Computing: Levando Código Para Perto do Usuário
Edge computing leva serverless um passo além: em vez de rodar em uma região específica (us-east-1, por exemplo), seu código roda em data centers espalhados globalmente, próximos aos seus usuários.
Um usuário em São Paulo acessa o edge node brasileiro. Um usuário em Tóquio acessa o edge node japonês. Mesma aplicação, latência drasticamente reduzida.
A Diferença Entre Serverless Tradicional e Edge
AWS Lambda (Serverless Regional):
- Executa em uma região específica (ex: us-east-1)
- Cold start: 100-500ms
- Latência adicional para usuários distantes
Cloudflare Workers (Edge Computing):
- Executa em 300+ localidades globalmente
- Cold start: <10ms
- Latência consistentemente baixa globalmente
Casos de Uso Ideais Para Edge
Personalização de Conteúdo: Modificar HTML baseado em geolocalização, A/B testing, feature flags.
Autenticação e Autorização: Verificar tokens JWT antes de requests chegarem ao backend.
API Gateways: Roteamento inteligente, rate limiting, caching.
Middleware de Requisições: Headers, redirects, rewrite de URLs.
Cloudflare Workers: Edge Computing na Prática
Cloudflare Workers é a plataforma de edge computing mais popular em 2025. Vamos ver um exemplo prático:
Exemplo 1: API de Geolocalização com Cache Inteligente
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Informações de geolocalização disponíveis automaticamente
const country = request.cf.country;
const city = request.cf.city;
const timezone = request.cf.timezone;
// Cache key baseado em localização
const cacheKey = `geo:${country}:${city}`;
// Verificar cache no KV (key-value store do Cloudflare)
let data = await env.GEO_CACHE.get(cacheKey, { type: 'json' });
if (!data) {
// Buscar dados customizados para essa localização
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 busca de dados 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',
};
return currencies[country] || 'USD';
}Este worker roda no edge mais próximo do usuário, detecta automaticamente a localização, e retorna dados personalizados com latência mínima.
Exemplo 2: Autenticação JWT no Edge
import { verify } from '@tsndr/cloudflare-worker-jwt';
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Rotas públicas não requerem auth
const publicRoutes = ['/health', '/login', '/register'];
if (publicRoutes.includes(url.pathname)) {
return fetch(request);
}
// Extrair token do 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 no edge (sem chamar backend!)
const isValid = await verify(token, env.JWT_SECRET);
if (!isValid) {
return new Response('Invalid token', { status: 401 });
}
// Decodificar payload para adicionar ao request
const { payload } = jwt.decode(token);
// Clonar request e adicionar user info nos headers
const modifiedRequest = new Request(request);
modifiedRequest.headers.set('X-User-Id', payload.userId);
modifiedRequest.headers.set('X-User-Role', payload.role);
// Encaminhar para origin
return fetch(modifiedRequest);
} catch (error) {
return new Response('Token verification failed', { status: 401 });
}
},
};Essa abordagem verifica autenticação no edge, antes da requisição chegar ao seu backend, economizando latência e carga nos servidores.
AWS Lambda@Edge: Serverless na CDN da Amazon
AWS Lambda@Edge permite rodar funções Lambda nos edge locations do CloudFront (200+ localizações).
Exemplo: Redirecionamento Inteligente Baseado em 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);
// Redirecionar para versões otimizadas
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 otimização
request.headers['x-device-type'] = [{
key: 'X-Device-Type',
value: isMobile ? 'mobile' : isTablet ? 'tablet' : 'desktop',
}];
return request;
};Exemplo: Geração de Imagens Responsivas no 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;
// Extrair 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 imagem original do S3
const s3Object = await s3.getObject({
Bucket: 'my-images-bucket',
Key: request.uri.substring(1), // remove leading /
}).promise();
// Processar imagem com Sharp
const processedImage = await sharp(s3Object.Body)
.resize(width, null, { withoutEnlargement: true })
.toFormat(format, { quality })
.toBuffer();
// Retornar imagem processada
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 no Edge
Vercel Edge Functions são otimizadas para Next.js e rodam no edge globalmente.
Exemplo: A/B Testing no Edge
// app/middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// Bucket aleatório para A/B test (0-99)
const bucket = Math.floor(Math.random() * 100);
// 50% dos usuários veem variante A, 50% veem B
const variant = bucket < 50 ? 'A' : 'B';
// Clonar response para adicionar cookie
const response = NextResponse.next();
// Armazenar variante no cookie (persistência entre páginas)
response.cookies.set('ab-test-variant', variant, {
maxAge: 60 * 60 * 24 * 30, // 30 dias
});
// Adicionar header para analytics
response.headers.set('X-AB-Test-Variant', variant);
// Rewrite baseado na 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'],
};Exemplo: Rate Limiting no 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;
// Limpar entradas antigas
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 janela
rateLimit.set(ip, { count: 1, timestamp: now });
} else if (userLimit.count >= maxRequests) {
// Limite 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();
}
Padrões de Arquitetura Serverless Moderna
1. Backend for Frontend (BFF) Pattern
// Cloudflare Worker atuando como BFF
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Diferentes backends para diferentes clients
if (url.pathname.startsWith('/api/mobile')) {
// Mobile recebe dados otimizados (menos campos)
const data = await fetchFromBackend(env.MOBILE_API);
return new Response(JSON.stringify({
...data,
_optimized: true,
}));
}
if (url.pathname.startsWith('/api/web')) {
// Web recebe dados 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}`);
// Processar imagem
const originalImage = await s3.getObject({ Bucket: bucket, Key: key }).promise();
// Gerar thumbnails em 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 no Edge
export default {
async fetch(request, env, ctx) {
const cache = caches.default;
const cacheKey = new Request(request.url, request);
// Verificar cache primeiro
let response = await cache.match(cacheKey);
if (!response) {
// Cache miss - buscar do backend
response = await fetch(request);
// Cachear se status for 200
if (response.status === 200) {
// Clonar response para cachear (pode ser consumida apenas 1x)
const responseToCache = response.clone();
// Adicionar ao cache (assíncrono via waitUntil)
ctx.waitUntil(cache.put(cacheKey, responseToCache));
}
}
return response;
},
};
Desafios e Considerações Práticas
Cold Starts: O Calcanhar de Aquiles
Funções serverless sofrem de "cold starts" quando ficam inativas. Estratégias para mitigar:
1. Keep-Alive Pings: Invocar funções periodicamente para mantê-las warm
2. Provisioned Concurrency (AWS): Manter instâncias sempre warm (custo adicional)
3. Edge Computing: Workers têm cold starts drasticamente menores (<10ms)
Limites de Execução
AWS Lambda: 15 minutos máximo
Cloudflare Workers: 50ms CPU time (plano free), 50ms-30s (plano pago)
Vercel Edge: 30 segundos
Para processamentos longos, considere split em múltiplas funções ou usar Step Functions.
Monitoramento e Debugging
Serverless dificulta debugging tradicional. Use:
- Structured Logging: JSON logs para fácil parsing
- Distributed Tracing: AWS X-Ray, Datadog, Sentry
- Metrics: CloudWatch, Prometheus para monitorar latência e erros
O Futuro: Edge-First Architecture
Em 2025, a tendência é clara: edge-first. Aplicações modernas estão sendo desenhadas desde o início para rodar no edge, aproveitando:
- Baixa latência global: Usuários no Brasil e Japão têm a mesma experiência
- Escalabilidade automática: De 0 a milhões sem configuração
- Custo otimizado: Pague apenas pelo que usa
- Resiliência: Distribuído globalmente, sem single point of failure
Se você está construindo aplicações web modernas, serverless e edge computing não são mais "nice to have" - são essenciais para competir em performance e experiência do usuário.
Se você se sente inspirado pelo poder do serverless e edge computing, recomendo que dê uma olhada em outro artigo: Microfrontends: Arquitetura Modular onde você vai descobrir como combinar edge computing com arquitetura de microfrontends para criar aplicações verdadeiramente escaláveis.
Bora pra cima! 🦅
📚 Quer Aprofundar Seus Conhecimentos em JavaScript?
Este artigo cobriu serverless e edge computing, mas há muito mais para explorar no mundo do desenvolvimento moderno.
Desenvolvedores que investem em conhecimento sólido e estruturado tendem a ter mais oportunidades no mercado.
Material de Estudo Completo
Se você quer dominar JavaScript do básico ao avançado, preparei um guia completo:
Opções de investimento:
- R$9,90 (pagamento único)
💡 Material atualizado com as melhores práticas do mercado

