Aula 2 - Módulo 7: Distribuição global e otimização de latência
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.
CDN inteligente distribui código e dados globalmente, garantindo performance consistente independente da localização do usuário.
Edge computing escala automaticamente baseado na demanda regional, otimizando custos e garantindo disponibilidade global.
Cache distribuído no edge reduz carga nos servidores origin e acelera responses para queries frequentes.
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/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);
}
// 📁 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
}
// 📁 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();
Na próxima aula, vamos explorar Edge Computing e CDN, implementando aplicações tRPC distribuídas globalmente com edge functions e cache inteligente.