MÓDULO 06 · CONCEITO 10 DE 12

CDN & edge caching

Akamai (1998), Cloudflare, Fastly. Origin shielding, surrogate keys, anycast routing. Edge compute (Workers, Functions). Por que mover lógica para a borda mudou a forma como APIs respondem em escala global.

Tempo de leitura ~22 min Pré-requisito Conceito 09 (HTTP cache RFC 9111) Próximo Performance de banco

Em fevereiro de 1998, no MIT, Tom Leighton (matemático, hoje CEO) e Daniel Lewin (engenheiro, falecido em 11 de setembro de 2001 no voo American 11) publicaram a ideia que viria a se chamar content delivery network. A intuição era responder a um problema concreto da web crescente: o site da Disney, ou qualquer site grande de evento (Olimpíadas, Copa do Mundo), recebia picos de tráfego que matavam servidores origin localizados em um único lugar do mundo. A solução de Leighton/Lewin: replicar o conteúdo em servidores espalhados geograficamente, e roteá-lo de modo que cada usuário receba do mais próximo. A empresa que fundaram — Akamai — virou sinônimo de CDN por uma década.

Hoje, CDN é infraestrutura básica da web. Cloudflare (2009), Fastly (2011), CloudFront da AWS, Google Cloud CDN, Azure Front Door — uma dúzia de provedores grandes operam dezenas de milhares de pontos de presença distribuídos globalmente. Sites e APIs sem CDN são exceção em 2026; quem opera um sistema com pretensão global e não tem CDN está deixando latência, custo, e disponibilidade na mesa.

Este conceito articula o que CDN faz por baixo (anycast routing, origin shielding, hierarquia de caches), explica os mecanismos de invalidação modernos (TTL, purge por URL, surrogate keys), e fecha com a tendência mais relevante da última década: edge compute (Cloudflare Workers, CloudFront Functions, Fastly Compute@Edge) — capacidade de rodar lógica em centenas de pontos de presença, redefinindo onde a computação acontece.

A premissa: CDN é cache HTTP em escala geográfica. As regras de Cache-Control, ETag, Vary do conceito 09 todas se aplicam — CDNs honram a spec. O que CDN adiciona é localização (servidor perto do usuário), escala (capacidade de absorver pico), e features (purge, edge compute) que cache HTTP cliente-side não tem.

O que CDN entrega — três benefícios

CDN moderna entrega três coisas em uma única camada. Articular cada uma define quando vale a pena adotar e configurar.

Latência reduzida via proximidade

Conceito 02 do módulo mostrou que round-trip cross-continent é 150–250 ms. Usuário em São Paulo acessando origin em US East paga ~150 ms de RTT mínimo, antes de qualquer processamento. Com CDN tendo PoP (point of presence) em São Paulo, o RTT cai para < 10 ms. Para conteúdo cacheado, essa é a diferença entre "usuário sente como local" e "usuário sente como cross-region". Cloudflare opera ~310 PoPs em 2026; Akamai mais de 4000.

Origin offload

Cada request servida do CDN é uma request que não atinge o origin. Em sistemas com cache hit rate alto (90%+), origin recebe 1/10 do tráfego total. Isso reduz custo de infraestrutura linearmente, e permite que origin pequeno sustente tráfego de escala. Wikipedia, com fração mínima de servidores próprios em comparação a competidores, opera em parte porque o cache de Squid + CDN responde a ~90% dos requests.

DDoS protection e edge processing

CDN moderna tem capacidade de rede que absorve ataques DDoS automaticamente — Cloudflare claims mitigar > 200 Tbps. Edge também faz validações básicas (IP allowlist, rate limiting, WAF) antes de o tráfego chegar ao origin. Em sistemas que sofrem ataques regulares (gaming, fintech, aposta), CDN é camada de defesa quase obrigatória.

Anycast routing — como o CDN te entrega ao PoP certo

O mecanismo que distribui tráfego globalmente é anycast IP. Em DNS tradicional (unicast), um IP corresponde a um servidor; em anycast, vários servidores em locais distintos anunciam o mesmo IP via BGP, e a infraestrutura de roteamento da internet entrega o pacote ao servidor "mais próximo" segundo métricas de BGP (geralmente proximidade geográfica + condições de rede).

O resultado: usuário em São Paulo digitando IP do CDN é roteado automaticamente para o PoP de São Paulo; usuário em Berlim é roteado para o PoP em Frankfurt ou Amsterdã. Sem que o cliente precise saber. Sem geolookup em DNS. Sem latência adicional.

Cloudflare e Fastly usam anycast religiosamente. CloudFront da AWS usa mistura de anycast com geo-DNS. Akamai historicamente usa geo-DNS (resolve para IP diferente conforme localização do resolver).

Hierarquia de caches — origin shielding

Em uma CDN típica, o cliente atinge o PoP mais próximo (edge). Se o edge tem cache hit, serve direto. Se cache miss, o edge precisa buscar do origin. Sem origin shielding, todos os edges fazem essa chamada independentemente — em pico, milhares de PoPs podem chamar o origin simultaneamente.

Origin shielding introduz uma camada intermediária. Em vez de cada edge ir direto ao origin, eles vão a um "shield PoP" — geralmente um PoP central por região. Esse shield serve como cache compartilhado entre todos os edges da região. Resultado: origin recebe no máximo um request por região por TTL, em vez de um por PoP.

Cloudflare chama de "Argo Tiered Caching", Fastly de "Origin Shield". Em cargas com cache hit rate alto, o ganho é marginal; em cargas com cold cache (deploy de novo conteúdo, evento ao vivo), faz diferença drástica — origin pode receber 1000× menos tráfego.

Cache key — o que o CDN usa para identificar entradas

Cada CDN constrói uma cache key única por entrada. A construção padrão é (host, path, query, vary headers). O detalhe importante: variações na cache key viram entradas separadas — se o cliente manda ?utm_source=google e ?utm_source=facebook, cada um vira cache miss separado.

O detalhe é importante porque parâmetros de tracking (UTM, fbclid, gclid) mudam por usuário/sessão sem afetar conteúdo. Configuração padrão do CDN cacheia cada combinação separada — efetivamente desabilitando cache. A defesa é configurar a CDN para ignorar esses parâmetros no cache key. Cloudflare tem "Cache Rules" que permitem isso; CloudFront tem "Cache Policy" com query string whitelist.

Vale também declarar Vary com cuidado. Como visto no conceito 09, Vary: User-Agent em CDN cria milhares de variantes — destrói cache. Sêniores que tocam CDN sabem essa armadilha.

Invalidação — TTL, purge, surrogate keys

A invalidação é onde CDN se diferencia. Há três modos.

TTL (TTL-based)

Mais simples. Conteúdo expira após N segundos. Configurado via Cache-Control: max-age do origin ou regras explícitas no CDN. Não exige coordenação entre origin e CDN — quando algo muda, você espera o TTL expirar.

Purge por URL

Quando o conteúdo de uma URL específica muda no origin, você chama API do CDN dizendo "invalide essa URL". Cloudflare: POST /zones/.../purge_cache; CloudFront: CreateInvalidation; Fastly: POST /service/.../purge/.... Em segundos, todos os PoPs descartam aquela entrada e buscam de novo do origin no próximo request.

Funciona bem para URLs individuais; vira problema quando você precisa invalidar muitas URLs simultaneamente — por exemplo, todos os produtos de uma categoria. APIs de purge tipicamente têm limites (1000 URLs por minuto) que tornam invalidação em massa difícil.

Surrogate keys (tagged invalidation)

A inovação que Fastly popularizou: o origin envia Surrogate-Key: tag1 tag2 tag3 em cada response, e o CDN indexa as entradas pelas tags. Quando algo muda, o origin chama "invalide tudo com tag X" — milhares de URLs viram inválidas instantaneamente.

Exemplo: response de /api/produtos/abc123 pode carregar Surrogate-Key: produto-abc123 categoria-eletronicos todos-produtos. Quando o produto muda, purge a tag produto-abc123 (uma entrada). Quando a categoria muda, purge categoria-eletronicos (todas as URLs daquela categoria). Quando há mudança sistêmica, purge todos-produtos.

Cloudflare lançou "Cache Tags" similar (em planos enterprise); CloudFront tem "Invalidate by tags" via Lambda@Edge customizado. Surrogate keys são o mecanismo que torna CDN viável em sistemas dinâmicos — sem ele, invalidar dado dinâmico é insustentável.

Edge compute — Workers, Functions, Compute@Edge

A revolução da última década: CDN deixou de ser só cache e virou plataforma de execução. Edge compute permite rodar código em centenas de PoPs ao redor do mundo, com latência sub-50ms para qualquer usuário.

Cloudflare Workers (lançado em 2017) foi o pioneiro — V8 isolates rodando JavaScript com cold start de microssegundos. Cada Worker pode interceptar requests HTTP, modificar response, fazer lookup em KV store, e retornar — tudo no PoP, sem jamais tocar origin.

CloudFront Functions e Lambda@Edge (AWS) entregam capacidades similares — Functions é mais limitado e barato (apenas modificação de header/URL); Lambda@Edge é mais poderoso (processamento completo) mas com cold start maior.

Fastly Compute@Edge (2020) usa WebAssembly como runtime — qualquer linguagem que compila para WASM (Rust, Go, AssemblyScript) roda no edge. Performance e segurança superiores ao V8 isolates em casos específicos.

Vercel Edge Functions, Deno Deploy, Bun Edge — novos players que reembalam a tecnologia para desenvolvedores web.

Casos típicos para edge compute: A/B testing (decidir variante por usuário sem viagem ao origin), autenticação leve (validar JWT), rewrites de URL, personalização de conteúdo estático, redirects geográficos, rate limiting customizado, manipulação de headers para CDN downstream. O denominador comum é "lógica que precisa ser global mas não precisa de dados centrais grandes".

O ciclo completo — request atravessando a stack

Para fixar como CDN se compõe com cache HTTP e cache aplicacional, considere uma request real atravessando o sistema completo:

USUÁRIO em SP                    request: GET /api/produtos/abc123
   │
   ▼
DNS resolve "api.example.com"     anycast → PoP de SP (Cloudflare)
   │  ~5 ms
   ▼
Cloudflare Worker (edge)          rate limit, geo check, A/B test
   │  ~2 ms
   ▼
Cloudflare Cache (PoP SP)         cache hit? → serve direto, 304/200
   │  hit: ~5 ms total. Done.
   │  miss: vai ao tier-1 cache
   ▼
Cloudflare Argo Tier 1            cache hit em região? → serve
   │  hit: ~30 ms total
   │  miss: vai ao origin
   ▼
Origin (US East, ASP.NET Core)    OutputCache hit? → serve
   │  hit: ~150 ms (RTT + processamento mínimo)
   │  miss: vai a Redis
   ▼
Redis (cache aplicacional)        hit? → serve. miss → banco
   │
   ▼
PostgreSQL (origem da verdade)    query, retorna
   │
   ▼ (responde para cima, cada camada cacheia)
Origin → Argo → PoP → Worker → Usuário

Em sistema bem ajustado, ~95% das requests são servidas em < 50 ms (cache hit em PoP); ~4% em < 200 ms (Argo ou OutputCache); ~1% chega ao banco. P50 do usuário fica próximo do RTT ao PoP mais próximo (10–20 ms); P99 fica em algo como 200 ms; P99.9 potencialmente em segundos quando algo dá errado.

Edge compute em código — o exemplo canônico

Para sentir como edge compute muda design, considere o exemplo canônico: rate limiting por usuário ou IP. Em arquitetura tradicional, esse limit é feito no origin — o request precisa chegar lá para ser rejeitado. No edge, é feito antes — origin nunca vê.

// Cloudflare Worker — rate limiting via Durable Objects ou KV
export default {
    async fetch(request, env) {
        const ip = request.headers.get("CF-Connecting-IP");
        const key = `ratelimit:${ip}`;

        const current = await env.KV.get(key, { type: "json" }) ?? { count: 0, ts: Date.now() };
        const now = Date.now();

        // janela de 60 segundos, 100 requests
        if (now - current.ts > 60_000) {
            current.count = 0;
            current.ts = now;
        }
        current.count++;

        if (current.count > 100) {
            return new Response("rate limited", { status: 429 });
        }

        await env.KV.put(key, JSON.stringify(current), { expirationTtl: 120 });

        // passa para origin
        return fetch(request);
    }
};

A consequência: tráfego de bot/scraper que abusaria do origin é cortado em milissegundos no edge, sem chegar. Custo do origin diminui; latência percebida por atacante sobe; capacidade do sistema escala.

Quando NÃO adotar CDN

CDN é útil em quase todo sistema com tráfego web. Há casos onde adicionar CDN não compensa.

Sistema interno em rede privada. APIs entre microsserviços no mesmo VPC não passam pela internet pública — CDN não tem como interceptar.

Conteúdo essencialmente único e personalizado. Se cada response é diferente (chat em tempo real, dashboard ultra-personalizado), cache hit rate é zero — CDN só adiciona latência.

Sistema sem volume. Para protótipos ou sistemas pequenos, custo operacional de configurar e operar CDN pode superar o ganho. Cloudflare tem tier gratuito que torna a barreira baixa, mas sempre há complexidade adicional.

Compliance / soberania de dados. Sistemas em áreas reguladas (saúde, financeiro, dados governamentais) podem ter restrições sobre onde dados podem ser cacheados. Adotar CDN sem articular isso é risco de compliance.

Cache em três frentes simultâneas

Para cobrir todos os ângulos de cache em uma API moderna, eis a estratégia composta que sêniores configuram:

C# — origin com OutputCache + Cache-Control headers
app.MapGet("/api/produtos/{id}", async (Guid id, IProdutoRepository repo, HttpContext ctx) => {
    var produto = await repo.ObterAsync(id);
    if (produto is null) return Results.NotFound();

    var etag = $"\"{produto.UpdatedAt.Ticks}\"";
    if (ctx.Request.Headers.IfNoneMatch == etag)
        return Results.StatusCode(304);

    ctx.Response.Headers.ETag = etag;

    // diretivas para CDN + browser
    ctx.Response.Headers.CacheControl =
        "public, max-age=60, s-maxage=300, stale-while-revalidate=600";

    // surrogate keys para invalidação dirigida via Cloudflare/Fastly
    ctx.Response.Headers.Append("Surrogate-Key",
        $"produto-{id} categoria-{produto.CategoriaId} all-products");

    return Results.Ok(produto);
})
.CacheOutput(p => p.Expire(TimeSpan.FromSeconds(60)).Tag("products"));

Note as três camadas: OutputCache server-side, Cache-Control para browser/CDN, Surrogate-Key para invalidação dirigida no CDN. Configuração rica em tags facilita purge preciso.

Python — FastAPI com cabeçalhos completos
from fastapi import FastAPI, Request, Response, HTTPException, status

@app.get("/api/produtos/{id}")
async def obter_produto(id: str, request: Request, response: Response):
    produto = await repo.obter(id)
    if produto is None:
        raise HTTPException(404)

    etag = f'"{produto.updated_at.timestamp()}"'
    if request.headers.get("If-None-Match") == etag:
        return Response(status_code=status.HTTP_304_NOT_MODIFIED)

    response.headers["ETag"] = etag
    response.headers["Cache-Control"] = (
        "public, max-age=60, s-maxage=300, stale-while-revalidate=600"
    )
    response.headers["Surrogate-Key"] = (
        f"produto-{id} categoria-{produto.categoria_id} all-products"
    )

    return produto.to_dict()

FastAPI: tudo manual via headers. Verboso mas explícito. Pode-se encapsular em decorator/middleware para padronizar entre endpoints.

Go — chi com middleware composto
// middleware que adiciona Cache-Control + Surrogate-Key
type CacheConfig struct {
    MaxAge   int      // segundos
    SMaxAge  int
    SWR      int
    KeyFn    func(*http.Request, any) []string
}

func WithCacheHeaders(cfg CacheConfig) func(http.Handler) http.Handler {
    cc := fmt.Sprintf("public, max-age=%d, s-maxage=%d, stale-while-revalidate=%d",
        cfg.MaxAge, cfg.SMaxAge, cfg.SWR)
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Cache-Control", cc)
            next.ServeHTTP(w, r)
        })
    }
}

// no handler — adiciona Surrogate-Key específico
func (h *Handlers) ObterProduto(w http.ResponseWriter, r *http.Request) {
    id := chi.URLParam(r, "id")
    produto, err := h.repo.Obter(r.Context(), id)
    if err != nil {
        http.NotFound(w, r); return
    }

    etag := fmt.Sprintf(`"%d"`, produto.Version)
    if r.Header.Get("If-None-Match") == etag {
        w.WriteHeader(http.StatusNotModified); return
    }

    w.Header().Set("ETag", etag)
    w.Header().Set("Surrogate-Key",
        fmt.Sprintf("produto-%s categoria-%s all-products",
            id, produto.CategoriaID))
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(produto)
}

// rota
r.With(WithCacheHeaders(CacheConfig{60, 300, 600, nil})).
  Get("/api/produtos/{id}", h.ObterProduto)

Em Go, padrão idiomático é middleware funcional que adiciona cabeçalhos, e handler complementa com surrogate keys específicas.

Anti-padrões frequentes

CDN sem origin shielding em pico. Sistema com TTL curto ou cache miss sob deploy faz todos os edges chamarem origin simultaneamente. Origin satura. Defesa: configurar tier-1 cache (Argo, Origin Shield).

Esquecer de configurar Vary. Endpoint retorna conteúdo diferente por Accept-Language, mas Vary não declara. Usuário em pt-BR vê página em en-US (ou vice-versa). Defesa: declarar todos os headers que afetam conteúdo.

Purge sem rate limit awareness. Equipe tenta purgar 100k URLs simultaneamente. CDN aplica throttle, deixa metade na fila, time pensa que invalidou — usuário vê dado obsoleto. Defesa: usar surrogate keys; ou monitorar API de purge para garantir conclusão.

Edge compute com estado em memória local. Worker mantém contador em memória. Funciona em testes (uma instância). Em produção, há centenas de instâncias do Worker rodando — cada uma com seu próprio contador. Estado global vira local. Defesa: usar KV store (Cloudflare KV, CloudFront Lambda@Edge com DynamoDB) para estado.

CDN como SPOF. Sistema dependente crítico de CDN único — se CDN sai, sistema sai. Cloudflare e Fastly tiveram outages globais (junho/2022 Cloudflare, junho/2021 Fastly). Defesa: multi-CDN com failover, ou pelo menos plano de bypass para origin direto em emergência.

armadilha em produção

Cache em endpoint que retorna dado de usuário, sem private. CDN cacheia "como público", usuário B recebe response do usuário A. Em sistemas com Cloudflare ou similar, o sintoma aparece como "vejo info de outra pessoa às vezes". Investigação revela header de autenticação não está em Vary, ou — pior — Cache-Control está public. Defesa estrutural: equipe deve ter teste automatizado que verifica que endpoints autenticados nunca retornam Cache-Control: public; CI bloqueia PR que viola. Alguns CDNs (Cloudflare) por padrão ignoram Authorization header em cache — defesa ajuda, mas configuração explícita é obrigação.

heurística do sênior

Antes de adotar CDN, articule: "que % do meu tráfego é cacheável?". Se for < 10%, CDN é principalmente para DDoS protection — vale, mas com expectativa ajustada. Se 10–50%, CDN reduz custo e latência consideravelmente. Se > 50%, CDN é transformador — origin pode ser dimensionado para fração do que seria sem ela. Articule também: "qual é o RTO de invalidação que preciso?". Em sistemas de e-commerce com mudança de preço, invalidação em segundos é necessário — usar surrogate keys. Em conteúdo editorial, minutos é OK — TTL basta. Em conteúdo verdadeiramente estático, horas/dias é OK — TTL longo + immutable.

Por que importa para a sua carreira

CDN é vocabulário que sêniores backend precisam ter independente de oportunidade. Em entrevistas para vagas que tocam web em escala, "como você configuraria CDN para esse sistema?" é pergunta direta. A resposta forte cita anycast, origin shielding, surrogate keys, edge compute, e articula trade-offs entre TTL e purge. Em revisão de código de novo endpoint, perceber falta de Cache-Control ou risco de vazamento por configuração CDN é serviço ao time. Em discussão de arquitetura, propor edge compute para um problema específico (rate limiting, A/B test) frequentemente muda o desenho do sistema. E em pos-mortem de outage de origin, articular "tinha origin shielding? Surrogate keys? Multi-CDN?" guia investigação para pontos estruturais.

Como praticar

  1. Setup gratuito de Cloudflare. Cloudflare tem tier gratuito que cobre necessidades básicas. Pegue um domínio (mesmo de teste), aponte DNS para Cloudflare, configure Page Rules (ou Cache Rules) para um endpoint qualquer. Use ferramenta de inspeção (browser DevTools) para verificar cabeçalho cf-cache-status: HIT nas respostas. Esse exercício torna concreto como CDN opera.
  2. Cloudflare Worker hello-world. Crie um Worker que adiciona header customizado a todas as responses, ou faz redirect baseado em país (geo-routing). Faça deploy via wrangler CLI. Mensure latência adicionada (deve ser ~1 ms). Esse exercício revela o quão acessível edge compute ficou.
  3. Multi-camada com surrogate keys. Em projeto seu, configure: OutputCache (.NET) ou equivalente no servidor; Cache-Control no response; Surrogate-Key com tags granulares; e API de purge no CDN (Cloudflare ou outro). Implemente endpoint que faz update e dispara purge das tags afetadas. Verifique o ciclo completo: primeiro request cacheia, update purga, próximo request retorna fresco. Esse setup, raro de ver em projetos reais, é diferencial em revisão.

Referências para aprofundar

  1. paper Globally Distributed Content Delivery — Akamai (IEEE Internet Computing, 2002). Paper técnico inicial da Akamai sobre como CDN funciona. Datado em hardware mas conceitualmente fundador.
  2. livro High Performance Browser Networking — Ilya Grigorik (O'Reilly, 2013). hpbn.co — Capítulos finais cobrem CDN, edge, otimização de delivery. Gratuito online, atualizado pelo autor.
  3. livro Web Performance in Action — Jeremy Wagner (Manning, 2017). Cap. sobre CDN cobre estratégias práticas com receitas. Voltado para web mas aplicável a APIs.
  4. docs Cloudflare Learning Center. cloudflare.com/learning — Documentação didática do Cloudflare cobrindo conceitos universais (anycast, BGP, DDoS). Útil mesmo se você não usa Cloudflare.
  5. docs Cloudflare Workers Documentation. developers.cloudflare.com/workers — Documentação canônica de edge compute moderno. Inclui exemplos práticos e padrões de design.
  6. docs AWS CloudFront Documentation. docs.aws.amazon.com/cloudfront — Cobertura completa do CloudFront, Functions, e Lambda@Edge. Importante para times que vivem em AWS.
  7. docs Fastly Surrogate Keys. developer.fastly.com/learning/concepts/cache-keys — A invenção que popularizou tag-based invalidation. Documentação direta do criador.
  8. artigo How CDN Works — Marek Majkowski (Cloudflare blog, 2020). blog.cloudflare.com — Engenheiro principal do Cloudflare explica internals com clareza rara. Inclui diagramas de routing real.
  9. artigo The Lambda@Edge Programming Model — Tara Hernandez (AWS blog, 2017+). aws.amazon.com/blogs/aws/lambda-at-edge-intelligent-processing-of-http-requests-at-the-edge — A apresentação inicial. Útil para entender modelo mental do edge compute AWS-style.
  10. artigo Why Cloudflare Workers — Kenton Varda (Cloudflare blog, 2018). blog.cloudflare.com/cloud-computing-without-containers — Varda (engenheiro principal de Workers) articula por que V8 isolates batem containers em cold start. Provocador e definidor.
  11. artigo Multi-CDN Strategies — Cedexis / Citrix. Várias publicações sobre estratégias multi-CDN para evitar SPOF. Útil para sistemas com SLO alto.
  12. vídeo The Edge of the Web — Mike McCall (Vercel, 2022). YouTube. Apresentação visual sobre como edge compute mudou desenvolvimento web. Voltado para front-end mas conceitual aplicável.