🚀 Oferta especial: 60% OFF no CrazyStack - Últimas vagas!Garantir vaga →

Edge Computing e CDN

Aula 2 - Módulo 7: Distribuição global e otimização de latência

🎯 Por que Edge Computing para tRPC?

⚡ Latência Ultra-Baixa

Edge functions executam próximo aos usuários, reduzindo latência de centenas para dezenas de milissegundos. Para aplicações tRPC críticas, isso significa UX superior.

🌐 Distribuição Global

CDN inteligente distribui código e dados globalmente, garantindo performance consistente independente da localização do usuário.

📊 Escalabilidade Automática

Edge computing escala automaticamente baseado na demanda regional, otimizando custos e garantindo disponibilidade global.

🔄 Cache Inteligente

Cache distribuído no edge reduz carga nos servidores origin e acelera responses para queries frequentes.

⚠️ Conceitos de Edge Computing

Edge Functions:

Código executado em edge locations próximas aos usuários

CDN:

Content Delivery Network para cache e distribuição

Edge Cache:

Cache distribuído em múltiplas regiões

Cold Start:

Tempo inicial de carregamento de functions

⚡ Edge Functions para tRPC

🚀 Cloudflare Workers Implementation

edge/cloudflare-worker.ts
// 📁 edge/cloudflare-worker.ts
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server/api/root';

// 🌍 Edge-optimized tRPC client
const createEdgeClient = (region: string) => {
  return createTRPCProxyClient<AppRouter>({
    links: [
      httpBatchLink({
        url: `https://api-${region}.trpc-app.com/trpc`,
        headers: {
          'CF-Ray': self.CF_RAY || '',
          'CF-IPCountry': self.CF_IPCountry || '',
        },
      }),
    ],
  });
};

// 🎯 Main edge function
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    const userCountry = request.headers.get('CF-IPCountry') || 'US';
    const userRegion = getOptimalRegion(userCountry);
    
    // 🔍 Route based on request type
    if (url.pathname.startsWith('/api/trpc')) {
      return handleTRPCRequest(request, userRegion, env, ctx);
    }
    
    if (url.pathname.startsWith('/edge-cache')) {
      return handleCacheRequest(request, env, ctx);
    }
    
    return new Response('Not Found', { status: 404 });
  },
};

// 🎯 Handle tRPC requests at the edge
async function handleTRPCRequest(
  request: Request,
  region: string,
  env: Env,
  ctx: ExecutionContext
): Promise<Response> {
  const url = new URL(request.url);
  const procedure = url.pathname.replace('/api/trpc/', '');
  const cacheKey = `trpc:${procedure}:${url.search}`;
  
  // 🗂️ Try edge cache first
  const cached = await env.EDGE_CACHE.get(cacheKey);
  if (cached) {
    console.log(`🎯 Edge cache HIT: ${procedure}`);
    return new Response(cached, {
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': 'public, max-age=60',
        'X-Cache': 'HIT',
      },
    });
  }
  
  console.log(`❌ Edge cache MISS: ${procedure}`);
  
  try {
    // 🔄 Proxy to optimal region
    const client = createEdgeClient(region);
    const startTime = Date.now();
    
    // 📊 Execute based on request method
    let result;
    if (request.method === 'GET') {
      const input = url.searchParams.get('input');
      const parsedInput = input ? JSON.parse(input) : undefined;
      result = await (client as any)[procedure].query(parsedInput);
    } else if (request.method === 'POST') {
      const body = await request.json();
      result = await (client as any)[procedure].mutate(body);
    }
    
    const duration = Date.now() - startTime;
    
    // 💾 Cache successful responses
    if (request.method === 'GET' && result) {
      const ttl = getCacheTTL(procedure);
      ctx.waitUntil(
        env.EDGE_CACHE.put(cacheKey, JSON.stringify(result), { 
          expirationTtl: ttl 
        })
      );
    }
    
    // 📊 Record metrics
    ctx.waitUntil(recordMetrics(procedure, duration, region, env));
    
    return new Response(JSON.stringify(result), {
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': `public, max-age=${getCacheTTL(procedure)}`,
        'X-Cache': 'MISS',
        'X-Region': region,
        'X-Duration': `${duration}ms`,
      },
    });
    
  } catch (error) {
    console.error(`Edge function error:`, error);
    
    return new Response(JSON.stringify({ 
      error: 'Internal Server Error',
      code: 'EDGE_ERROR' 
    }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' },
    });
  }
}

// 🌍 Determine optimal region for user
function getOptimalRegion(country: string): string {
  const regionMap: Record<string, string> = {
    // North America
    'US': 'us-east-1',
    'CA': 'us-east-1',
    'MX': 'us-east-1',
    
    // Europe
    'GB': 'eu-west-1',
    'DE': 'eu-west-1',
    'FR': 'eu-west-1',
    'IT': 'eu-west-1',
    'ES': 'eu-west-1',
    
    // Asia Pacific
    'JP': 'ap-northeast-1',
    'KR': 'ap-northeast-1',
    'SG': 'ap-southeast-1',
    'AU': 'ap-southeast-2',
    'IN': 'ap-south-1',
    
    // South America
    'BR': 'sa-east-1',
    'AR': 'sa-east-1',
  };
  
  return regionMap[country] || 'us-east-1';
}

// 🕐 Get cache TTL based on procedure type
function getCacheTTL(procedure: string): number {
  const ttlMap: Record<string, number> = {
    'user.getProfile': 300,     // 5 minutes
    'post.getById': 600,        // 10 minutes
    'post.getRecent': 60,       // 1 minute
    'auth.getSession': 0,       // No cache
    'analytics.track': 0,       // No cache
  };
  
  // Default cache for GET operations
  return ttlMap[procedure] || 180; // 3 minutes default
}

// 📊 Record edge metrics
async function recordMetrics(
  procedure: string,
  duration: number,
  region: string,
  env: Env
): Promise<void> {
  const metrics = {
    timestamp: Date.now(),
    procedure,
    duration,
    region,
    datacenter: env.CF_RAY?.split('-')[1] || 'unknown',
  };
  
  // Send to analytics
  await env.ANALYTICS.writeDataPoint(metrics);
}

🗺️ Multi-Region Deployment

infrastructure/terraform/global-deployment.tf
// 📁 infrastructure/terraform/global-deployment.tf
# 🌐 Global infrastructure for tRPC API

# 🇺🇸 US East (Primary)
resource "aws_instance" "trpc_api_us_east" {
  count             = 3
  ami               = "ami-0abcdef1234567890"
  instance_type     = "t3.large"
  availability_zone = data.aws_availability_zones.us_east.names[count.index]
  
  tags = {
    Name        = "trpc-api-us-east-${count.index + 1}"
    Region      = "us-east-1"
    Environment = "production"
    Service     = "trpc-api"
  }
}

# 🇪🇺 Europe West (Secondary)
resource "aws_instance" "trpc_api_eu_west" {
  provider          = aws.eu_west
  count             = 2
  ami               = "ami-0123456789abcdef0"
  instance_type     = "t3.medium"
  
  tags = {
    Name        = "trpc-api-eu-west-${count.index + 1}"
    Region      = "eu-west-1"
    Environment = "production"
    Service     = "trpc-api"
  }
}

# 🔄 Global Load Balancer
resource "aws_route53_record" "api_global" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"
  
  set_identifier = "primary"
  
  failover_routing_policy {
    type = "PRIMARY"
  }
  
  health_check_id = aws_route53_health_check.primary.id
}

🚀 Edge Computing Strategies

src/lib/edge/performance-optimizer.ts
// 📁 src/lib/edge/performance-optimizer.ts
import { TRPCError } from '@trpc/server';

class EdgePerformanceOptimizer {
  private cache: Cache;

  constructor() {
    this.cache = caches.default;
  }

  // 🎯 Smart caching strategy
  async optimizeResponse<T>(
    request: Request,
    handler: () => Promise<T>,
    config: CacheConfig
  ): Promise<{ data: T; metadata: ResponseMetadata }> {
    const startTime = performance.now();
    const cacheKey = this.generateCacheKey(request);
    
    // 🔍 Try cache first
    const cachedResponse = await this.getCachedResponse<T>(cacheKey);
    if (cachedResponse) {
      return {
        data: cachedResponse.data,
        metadata: {
          cached: true,
          age: Date.now() - cachedResponse.timestamp,
          responseTime: performance.now() - startTime,
        },
      };
    }

    // 🔄 Execute handler and cache result
    const data = await handler();
    await this.cacheResponse(cacheKey, data, config);
    
    return {
      data,
      metadata: {
        cached: false,
        age: 0,
        responseTime: performance.now() - startTime,
      },
    };
  }
}

export const edgeOptimizer = new EdgePerformanceOptimizer();

✅ O que você conquistou nesta aula

API Gateway pattern com tRPC
Service Discovery automático
Service Mesh com Istio
mTLS security policies
Event-Driven architecture
CQRS pattern implementation
Distributed Tracing completo
OpenTelemetry integration

🎯 Próximos Passos

Na próxima aula, vamos explorar Edge Computing e CDN, implementando aplicações tRPC distribuídas globalmente com edge functions e cache inteligente.

Módulo Anterior
Módulo 7
Aula 1 de 5
Arquiteturas Distribuídas
Próxima Aula