Voltar para o Blog

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.

Bora pra cima! 🦅

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário