Pular para o conteúdo principal

Cache strategy (não-técnico)

Esta página explica, sem assumir conhecimento de Cloudflare, Workers ou caching, como o cache funciona na plataforma e o que esperar quando algo muda em produção.

Para o lado técnico (APIs, arquivos, fluxos de dados), veja Cache architecture. Para "como faço pra forçar X agora", veja Cache operations.

TL;DR (pra quem tem 30 segundos)

  • A plataforma guarda cópias temporárias das respostas do BFF em vários lugares ("cache") pra abrir página rápido.
  • Cada tipo de dado tem um prazo de validade (TTL). Quando vence, a próxima visita busca dado fresco.
  • O TTL do brandConfig (a maioria do que muda no backoffice) é 1 minuto. Tudo mais novo entra automaticamente em até 1min sem ninguém precisar fazer nada.
  • Pra coisas que não são brandConfig (catálogo de jogos, top wins, etc) o TTL é mais longo. Quando precisa atualizar fora desse prazo, alguém roda um workflow no GitHub Actions (Manual Cache Purge) e o cache é zerado.
  • Tem 5 camadas de cache no caminho — não uma só. A boa notícia: o workflow de purge sabe atualizar todas em uma operação só.

Por que precisa de cache?

A plataforma serve dezenas de milhões de páginas por dia. Cada uma envolve dezenas de chamadas ao backend (config da marca, catálogo de jogos, estatísticas, banners, traduções, payment-providers...). Se cada visitante batesse no BFF (o backend principal) pra renderizar a home, o backend cairia em minutos.

A solução é guardar a resposta a primeira vez que ela é calculada, e servir de cópia local nas próximas visitas — até a cópia ficar "velha demais". Esse "velha demais" é o que a gente chama de TTL (Time To Live).

Como uma página vira lenta sem cache?

Pra renderizar a home anonima, o navegador pede o HTML. O servidor precisa:

  1. Saber qual brand é (brandConfig — banners, cores, features, idioma)
  2. Saber quais jogos mostrar (catálogo, "top wins", "high payers")
  3. Saber o usuário (se logado)
  4. Buscar promos ativas
  5. Aplicar overrides do brand
  6. Renderizar o HTML
  7. Mandar de volta

Cada item tem uma ou mais chamadas ao BFF. Sem cache:

  • ~10 chamadas BFF por requisição
  • Cada uma tem ~150-400ms de latência (CDN → BFF → DB → volta)
  • Total: 2-4 segundos por página
  • Multiplica isso por milhares de visitas/minuto → BFF não aguenta

Com cache:

  • 1ª visita: paga o custo (2-4s)
  • Próximas N visitas: lê do cache em ~10ms
  • BFF só vê 1 chamada a cada TTL minutos, não N

Resultado: mesma página em ~200ms, BFF tranquilo.

As 5 camadas em uma analogia

Imagine que você trabalha numa loja física com 5 funcionários em sequência. Cliente entra na porta principal:

  1. Porteiro (CF Zone Edge) — guarda HTMLs prontos pra páginas anônimas. Se já viu a página, entrega na hora sem incomodar ninguém.
  2. Recepcionista (Brand Worker — middleware) — verifica se a chamada é de API e, se for, tem cópia da resposta na gaveta.
  3. Gerente (platform-cache engine) — coordena as respostas lógicas grandes ("dados da home", "config da marca"). Se já tem na pasta, devolve. Se a pasta tá velha, devolve a cópia velha rapidinho e já manda buscar a nova em segundo plano.
  4. Estagiário (front-service-api proxy) — fica em Frankfurt (perto do BFF). Quando o gerente realmente precisa pedir pro BFF, o estagiário vai correndo, traz a resposta e ainda guarda cópia local pra próxima.
  5. Anotações do cliente (browser localStorage) — quando o cliente sai e volta, ele lembra das últimas N respostas pra carregar offline-ish.

Cada um tem prazo de validade próprio nas cópias dele. Quando todos topam que "tá velho", o caminho completo é refeito.

Os tipos de dados e seus prazos

Os principais tipos cacheados, com seus TTLs em produção:

O que éTTLReflete em backoffice em
Config da marca (banners, cores, features, payment-providers list)1 minaté 1min
Catálogo de jogos (lista, categorias)1-2haté 1-2h ou purge manual
Estatísticas (top wins, stats por jogo)30min-1haté 30min-1h ou purge manual
Detalhes de jogo individual1haté 1h ou purge manual
Termos legais1haté 1h
Sitemap1haté 1h

"Reflete em backoffice em" = quanto tempo entre alguém salvar uma mudança no backoffice e essa mudança aparecer no site sem que ninguém faça nada.

Como "puxa atualização" sem esperar o TTL

Quando alguém precisa que uma mudança apareça agora (mudança crítica no backoffice, fix emergencial), o caminho é:

  1. Vai no repositório front-ops no GitHub
  2. Actions → "Manual Cache Purge"
  3. Preenche:
    • environment: a brand/env (ex: vera-bet-br, prod-7k-bet-br)
    • tags: o tipo do dado a invalidar (ex: brand pra config, catalog pra jogos, payments pra pagamentos)
    • ou glob: padrão como games:* pra tudo que envolve jogos
  4. Run workflow
  5. Em 30s o cache foi limpo, próxima visita pega dado fresco

Não precisa fazer deploy. Purge é independente do código.

Quando deploy também atualiza cache?

Todo deploy inclui um purge automático — mas ele é condicional, não incondicional:

  1. O deploy gera um novo BUILD_ID (identificador único do deploy)
  2. Esse ID é usado como "etiqueta" em várias camadas de cache → cópias antigas viram órfãs e expiram
  3. Logo após o deploy, o workflow dispara purge automático pros principais resources se e somente se CACHE_PURGE_SECRET estiver configurado na brand/env. Se o secret não estiver setado, o step é pulado com aviso — não falha o deploy.
  4. O purge da plataforma (platform-cache) agora falha o deploy se retornar non-2xx. O purge do SSR/zone continua sendo aviso-only (não bloqueia).
  5. E faz um "warm-up": curl em 10 páginas-chave pra repopular o cache antes do tráfego real chegar

Isso vale pra deploy.yml do brand worker. O front-service-api é deployado separadamente.

Importante: um novo resource no front-ops/config/cache/defaults.yml não é ativado automaticamente quando o front-ops faz push. Ele precisa de um redeploy explícito do brand worker (o worker lê a policy em deploy-time via --var PLATFORM_CACHE_POLICY_JSON).

Tipos de problemas e o que fazer

"Mudei algo no backoffice e não vejo no site"

Provavelmente é brandConfig. Aguarde 1min. Se não voltar:

  1. Confirma se a mudança foi salva no backoffice e se aparece no /api/dev/cache-policy da brand.
  2. Roda manual-cache-purge.yml com tags: brand na env correspondente.
  3. Se ainda persistir, é provavelmente cache do navegador. Ctrl+Shift+R / abre em janela anônima.

"Adicionei um jogo novo e não aparece"

Catálogo tem TTL 1-2h. Pra forçar:

  1. Roda manual-cache-purge.yml com tags: catalog na env (ou glob: games:*).

Cache no Cloudflare é por DC (datacenter). Pode estar warm em um, frio em outro. Soluções:

  1. Roda manual-cache-purge.yml com scope: zone (purge global na zona CF).
  2. Ou aguarda — TTL do brandConfig é 1min, vai sincronizar.

"Site inteiro carregando dados velhos"

Cenário raro mas existe. Roda manual-cache-purge.yml com:

  • environment correta
  • (deixa tudo vazio = purgeAll)
  • scope: all
  • Vai limpar tudo: brand worker, service-api e zone CF.

"Aconteceu uma falha no BFF e quero saber se o site vai ficar OK"

Sim, há proteção. O platform-cache tem staleIfError: se o BFF cair, ele continua servindo a última cópia conhecida por até 6h (o staleIfErrorSeconds padrão, reduzido de 24h — entende-se que uma indisponibilidade do BFF por mais de 6h é improvável). E se nem ele tem, busca do KV snapshot global. Site não fica branco.

Quando NÃO usar purge?

  • Não tenta "limpar todo cache pra ver se resolve um bug do código". Cache não causa bugs de lógica, ele só atrasa atualizações. Bug é bug, vai aparecer depois também.
  • Não roda purge a cada 5 min "preventivamente". Anula o ponto do cache. Confia nos TTLs.
  • Não usa scope: zone casualmente. É operação cara (custo CF) e nuclear (afeta todos os arquivos cacheados, incluindo assets imutáveis). Use só quando realmente precisa.

Quem é dono do quê?

CamadaOwnerComo mexer
CF Zone EdgeDevOpsDashboard CF ou manual-cache-purge.yml scope: zone
Brand worker SSR cacheDev (auto via deploy)Bump de BUILD_ID = invalidação
Brand worker API cacheDev (whitelist em código)PR no front-web-base
platform-cache engineDev (policy) + DevOps (purge runtime)Policy: front-ops/config/cache/defaults.yml · Purge: manual-cache-purge.yml
service-api proxyDev (rules) + DevOps (purge runtime)Rules: front-ops/config/cache/service-api-defaults.yml · Purge: cascateado pelo brand worker
Browser localStorageusuárioLogout limpa caches do api-client

Glossário

  • TTL (Time To Live) — quanto tempo a cópia em cache é considerada "fresca". Após o TTL, vira "stale" (velha).
  • SWR (Stale While Revalidate) — período extra depois do TTL onde a cópia velha ainda pode ser servida, enquanto uma cópia nova é buscada em segundo plano. Visitante sempre tem resposta rápida.
  • Stale-if-Error — período extra onde a cópia velha pode ser servida se o BFF tá fora do ar (graceful degradation).
  • Purge — apagar manualmente do cache (sem esperar TTL).
  • BUILD_ID — identificador único do deploy. Usado como etiqueta em namespaces de cache → todo deploy "invalida via namespace".
  • Resource — uma unidade lógica de dado cacheada (brandConfig, homeRows, etc).
  • Tag — palavra-chave declarada num resource (brand, catalog, games:list). Permite purges agrupados.
  • KV — armazenamento global da Cloudflare, cross-DC. Usado como fallback estável para resources críticos.
  • Cache API — o cache de edge da Cloudflare, por datacenter. Mais rápido que KV mas não cross-DC.