Voltar para o Blog

Edge Functions e o Futuro do Serverless: Arquitetura Moderna em 2025

Olá HaWkers, o mundo serverless evoluiu significativamente nos últimos anos, e 2025 marca a consolidação das Edge Functions como padrão para aplicações de alta performance. Se você ainda não está familiarizado com edge computing ou quer entender como aproveitar essa tecnologia, este artigo vai te guiar pelos conceitos e práticas mais importantes.

O que exatamente são Edge Functions? Por que elas oferecem performance superior às funções serverless tradicionais? E como você pode implementá-las em seus projetos? Vamos explorar tudo isso com exemplos práticos.

O Que São Edge Functions

Edge Functions são funções serverless que executam em servidores distribuídos geograficamente, próximos aos usuários finais. Diferente de funções tradicionais que rodam em regiões específicas, o edge computing leva a computação para a borda da rede.

Diferença Entre Serverless Tradicional e Edge

Serverless Tradicional:

  • Executa em regiões específicas (us-east-1, eu-west-1, etc.)
  • Latência depende da distância do usuário ao datacenter
  • Cold start pode ser significativo (centenas de ms a segundos)
  • Ambiente Node.js completo geralmente disponível

Edge Functions:

  • Executam em centenas de pontos de presença globais
  • Latência consistentemente baixa independente da localização
  • Cold start minimal (poucos milissegundos)
  • Runtime otimizado baseado em V8 ou similar

💡 Contexto: Para um usuário no Brasil acessando uma função em us-east-1, a latência de rede pode ser 100-200ms. Com edge, essa latência cai para 10-30ms.

Por Que Edge Functions Dominam em 2025

A adoção de edge functions cresceu exponencialmente por várias razões:

1. Performance Global

Com servidores em mais de 300 locais ao redor do mundo, usuários de qualquer lugar têm latência similar e baixa.

2. Custo-Benefício

Apesar do custo por execução similar, a menor latência significa menos tempo de espera e melhor experiência, justificando o investimento.

3. Casos de Uso Expandidos

Inicialmente usadas apenas para redirecionamentos simples, agora suportam:

Casos de uso modernos:

  • Autenticação e autorização
  • Personalização de conteúdo
  • A/B testing
  • Rate limiting
  • Manipulação de headers
  • Renderização server-side
  • APIs completas

4. Ecossistema Maduro

Plataformas como Cloudflare Workers, Vercel Edge Functions, Deno Deploy e AWS CloudFront Functions amadureceram significativamente.

Implementando Edge Functions na Prática

Vamos ver exemplos práticos usando diferentes plataformas.

Vercel Edge Functions

Perfeitas para projetos Next.js:

// pages/api/geo.ts ou app/api/geo/route.ts
import { NextRequest, NextResponse } from 'next/server';

export const config = {
  runtime: 'edge', // Define que é edge function
};

export default function handler(req: NextRequest) {
  // Informações de geolocalização disponíveis automaticamente
  const country = req.geo?.country ?? 'Desconhecido';
  const city = req.geo?.city ?? 'Desconhecida';
  const region = req.geo?.region ?? 'Desconhecida';

  return NextResponse.json({
    message: `Olá visitante de ${city}, ${region}, ${country}!`,
    latency: 'Esta resposta veio do edge mais próximo de você',
    timestamp: new Date().toISOString(),
  });
}

Cloudflare Workers

Uma das plataformas mais populares para edge:

// worker.ts
export interface Env {
  MY_KV: KVNamespace;
}

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    const url = new URL(request.url);

    // Rate limiting simples usando KV
    const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown';
    const rateLimitKey = `ratelimit:${ip}`;

    const currentCount = await env.MY_KV.get(rateLimitKey);
    const count = currentCount ? parseInt(currentCount) : 0;

    if (count > 100) {
      return new Response('Rate limit exceeded', { status: 429 });
    }

    // Incrementa contador com TTL de 1 minuto
    ctx.waitUntil(
      env.MY_KV.put(rateLimitKey, String(count + 1), {
        expirationTtl: 60
      })
    );

    // Lógica principal
    if (url.pathname === '/api/data') {
      const data = await fetchDataFromOrigin();
      return new Response(JSON.stringify(data), {
        headers: { 'Content-Type': 'application/json' },
      });
    }

    return new Response('Not Found', { status: 404 });
  },
};

async function fetchDataFromOrigin() {
  // Simula busca de dados
  return { message: 'Dados do edge', timestamp: Date.now() };
}

Edge Computing em ação

Deno Deploy

Plataforma nativa para edge com Deno:

// server.ts
import { serve } from 'https://deno.land/std/http/server.ts';

interface RequestInfo {
  method: string;
  url: string;
  userAgent: string | null;
  region: string | null;
}

serve(async (request: Request): Promise<Response> => {
  const requestInfo: RequestInfo = {
    method: request.method,
    url: request.url,
    userAgent: request.headers.get('user-agent'),
    region: Deno.env.get('DENO_REGION') ?? 'unknown',
  };

  // Roteamento simples
  const url = new URL(request.url);

  switch (url.pathname) {
    case '/':
      return new Response('Hello from Deno Edge!', {
        headers: { 'content-type': 'text/plain' },
      });

    case '/api/info':
      return new Response(JSON.stringify(requestInfo), {
        headers: { 'content-type': 'application/json' },
      });

    case '/api/time':
      const now = new Date();
      return new Response(
        JSON.stringify({
          utc: now.toUTCString(),
          iso: now.toISOString(),
          region: requestInfo.region,
        }),
        { headers: { 'content-type': 'application/json' } }
      );

    default:
      return new Response('Not Found', { status: 404 });
  }
});

Padrões Avançados com Edge Functions

Middleware de Autenticação

// middleware.ts (Next.js Edge Middleware)
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify } from 'jose';

const PUBLIC_PATHS = ['/', '/login', '/api/auth'];
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // Permite rotas públicas
  if (PUBLIC_PATHS.some(path => pathname.startsWith(path))) {
    return NextResponse.next();
  }

  // Verifica token JWT
  const token = request.cookies.get('auth-token')?.value;

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  try {
    const { payload } = await jwtVerify(token, JWT_SECRET);

    // Adiciona info do usuário aos headers
    const response = NextResponse.next();
    response.headers.set('x-user-id', payload.sub as string);
    response.headers.set('x-user-role', payload.role as string);

    return response;
  } catch (error) {
    // Token inválido
    const response = NextResponse.redirect(new URL('/login', request.url));
    response.cookies.delete('auth-token');
    return response;
  }
}

export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico).*)',
  ],
};

A/B Testing no Edge

// Cloudflare Worker para A/B testing
export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);

    // Verifica cookie existente ou atribui variante
    const cookies = request.headers.get('Cookie') ?? '';
    let variant = getCookie(cookies, 'ab-variant');

    if (!variant) {
      // Atribui variante aleatoriamente (50/50)
      variant = Math.random() < 0.5 ? 'A' : 'B';
    }

    // Modifica resposta baseado na variante
    const response = await fetch(request);
    const html = await response.text();

    let modifiedHtml = html;
    if (variant === 'B') {
      // Aplica mudanças da variante B
      modifiedHtml = html.replace(
        '<button class="cta">Comprar Agora</button>',
        '<button class="cta-new">Adicionar ao Carrinho</button>'
      );
    }

    const newResponse = new Response(modifiedHtml, response);

    // Define cookie para manter consistência
    newResponse.headers.append(
      'Set-Cookie',
      `ab-variant=${variant}; Path=/; Max-Age=604800`
    );

    return newResponse;
  },
};

function getCookie(cookies: string, name: string): string | null {
  const match = cookies.match(new RegExp(`${name}=([^;]+)`));
  return match ? match[1] : null;
}

Limitações e Considerações

O Que Edge Functions Não Fazem Bem

Limitações importantes:

  • Tempo de execução limitado (geralmente 30s máximo, alguns 50ms)
  • Memória restrita (128MB típico)
  • Sem acesso a filesystem
  • APIs limitadas (sem Node.js nativo completo)
  • Conexões de longa duração problemáticas

Quando Usar Serverless Tradicional

Prefira serverless tradicional para:

  • Processamento intensivo de CPU
  • Operações de banco de dados complexas
  • Tarefas de longa duração
  • Quando precisa de ecossistema Node.js completo
  • Processamento de arquivos grandes

Arquitetura Híbrida

A melhor abordagem geralmente combina edge e serverless:

Usuário

Edge Function (autenticação, cache, personalização)

Serverless Function (lógica de negócio, banco de dados)

Banco de Dados / Serviços

Comparativo de Plataformas

Plataforma Cold Start Locais Linguagens Uso Gratuito
Cloudflare Workers ~0ms 300+ JS/TS, Rust, WASM 100k req/dia
Vercel Edge ~1ms 100+ JS/TS Conforme plano
Deno Deploy ~1ms 35+ JS/TS, WASM 1M req/mês
AWS CloudFront ~5ms 400+ JS Conforme uso
Fastly Compute ~5ms 70+ JS, Rust, WASM Conforme uso

Escolhendo a Plataforma Certa

Cloudflare Workers:

  • Melhor para aplicações standalone
  • Ecossistema mais maduro (KV, D1, R2)
  • Preços competitivos

Vercel Edge:

  • Ideal para projetos Next.js
  • Integração perfeita com framework
  • Edge Middleware poderoso

Deno Deploy:

  • Ótimo para quem prefere Deno
  • Deploy via GitHub simples
  • TypeScript first-class

Melhores Práticas

1. Cache Agressivo

// Implemente cache para respostas que podem ser cacheadas
export default {
  async fetch(request: Request): Promise<Response> {
    const cacheKey = new Request(request.url, request);
    const cache = caches.default;

    // Verifica cache primeiro
    let response = await cache.match(cacheKey);

    if (!response) {
      response = await fetch(request);

      // Clone para cachear
      response = new Response(response.body, response);
      response.headers.set('Cache-Control', 'public, max-age=3600');

      // Cache em background
      ctx.waitUntil(cache.put(cacheKey, response.clone()));
    }

    return response;
  },
};

2. Tratamento de Erros Robusto

export default {
  async fetch(request: Request): Promise<Response> {
    try {
      return await handleRequest(request);
    } catch (error) {
      console.error('Edge function error:', error);

      // Retorna resposta de erro amigável
      return new Response(
        JSON.stringify({
          error: 'Internal Error',
          message: 'Something went wrong',
        }),
        {
          status: 500,
          headers: { 'Content-Type': 'application/json' },
        }
      );
    }
  },
};

3. Monitoramento e Observabilidade

// Adicione logging estruturado
interface LogEntry {
  timestamp: string;
  level: 'info' | 'warn' | 'error';
  message: string;
  metadata?: Record<string, unknown>;
}

function log(entry: LogEntry) {
  console.log(JSON.stringify(entry));
}

export default {
  async fetch(request: Request): Promise<Response> {
    const startTime = Date.now();

    const response = await handleRequest(request);

    log({
      timestamp: new Date().toISOString(),
      level: 'info',
      message: 'Request handled',
      metadata: {
        url: request.url,
        method: request.method,
        status: response.status,
        duration: Date.now() - startTime,
      },
    });

    return response;
  },
};

Conclusão

Edge Functions representam uma evolução significativa na arquitetura serverless, oferecendo latência consistentemente baixa para usuários globais. Em 2025, elas se tornaram componente essencial para aplicações que priorizam performance.

A chave é entender quando usar edge versus serverless tradicional. Para autenticação, personalização, rate limiting e respostas rápidas, edge é ideal. Para processamento pesado e lógica complexa de negócio, serverless tradicional continua sendo a escolha certa.

A combinação de ambos oferece o melhor dos dois mundos: respostas rápidas no edge com poder de processamento no backend quando necessário.

Se você quer se aprofundar em arquiteturas modernas, recomendo que dê uma olhada em outro artigo: PWAs com JavaScript: A Revolução dos Aplicativos Web onde você vai descobrir como construir experiências web modernas e performáticas.

Bora pra cima! 🦅

🎯 Junte-se aos Desenvolvedores que Estão Evoluindo

Milhares de desenvolvedores já usam nosso material para acelerar seus estudos e conquistar melhores posições no mercado.

Por que investir em conhecimento estruturado?

Aprender de forma organizada e com exemplos práticos faz toda diferença na sua jornada como desenvolvedor.

Comece agora:

  • 1x de R$9,90 no cartão
  • ou R$9,90 à vista

🚀 Acessar Guia Completo

"Material excelente para quem quer se aprofundar!" - João, Desenvolvedor

Comentários (0)

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

Adicionar comentário