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:
- Saber qual brand é (
brandConfig— banners, cores, features, idioma) - Saber quais jogos mostrar (catálogo, "top wins", "high payers")
- Saber o usuário (se logado)
- Buscar promos ativas
- Aplicar overrides do brand
- Renderizar o HTML
- 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:
- 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.
- Recepcionista (Brand Worker — middleware) — verifica se a chamada é de API e, se for, tem cópia da resposta na gaveta.
- 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.
- 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.
- 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 é | TTL | Reflete em backoffice em |
|---|---|---|
| Config da marca (banners, cores, features, payment-providers list) | 1 min | até 1min |
| Catálogo de jogos (lista, categorias) | 1-2h | até 1-2h ou purge manual |
| Estatísticas (top wins, stats por jogo) | 30min-1h | até 30min-1h ou purge manual |
| Detalhes de jogo individual | 1h | até 1h ou purge manual |
| Termos legais | 1h | até 1h |
| Sitemap | 1h | até 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 é:
- Vai no repositório
front-opsno GitHub - Actions → "Manual Cache Purge"
- Preenche:
- environment: a brand/env (ex:
vera-bet-br,prod-7k-bet-br) - tags: o tipo do dado a invalidar (ex:
brandpra config,catalogpra jogos,paymentspra pagamentos) - ou glob: padrão como
games:*pra tudo que envolve jogos
- environment: a brand/env (ex:
- Run workflow
- 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:
- O deploy gera um novo
BUILD_ID(identificador único do deploy) - Esse ID é usado como "etiqueta" em várias camadas de cache → cópias antigas viram órfãs e expiram
- Logo após o deploy, o workflow dispara purge automático pros principais resources se e somente se
CACHE_PURGE_SECRETestiver configurado na brand/env. Se o secret não estiver setado, o step é pulado com aviso — não falha o deploy. - 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).
- 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.ymlnão é ativado automaticamente quando ofront-opsfaz 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:
- Confirma se a mudança foi salva no backoffice e se aparece no
/api/dev/cache-policyda brand. - Roda
manual-cache-purge.ymlcomtags: brandna env correspondente. - 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:
- Roda
manual-cache-purge.ymlcomtags: catalogna env (ouglob: games:*).
"Banner velho aparecendo em uma região mas não em outra"
Cache no Cloudflare é por DC (datacenter). Pode estar warm em um, frio em outro. Soluções:
- Roda
manual-cache-purge.ymlcomscope: zone(purge global na zona CF). - 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: zonecasualmente. É 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ê?
| Camada | Owner | Como mexer |
|---|---|---|
| CF Zone Edge | DevOps | Dashboard CF ou manual-cache-purge.yml scope: zone |
| Brand worker SSR cache | Dev (auto via deploy) | Bump de BUILD_ID = invalidação |
| Brand worker API cache | Dev (whitelist em código) | PR no front-web-base |
| platform-cache engine | Dev (policy) + DevOps (purge runtime) | Policy: front-ops/config/cache/defaults.yml · Purge: manual-cache-purge.yml |
| service-api proxy | Dev (rules) + DevOps (purge runtime) | Rules: front-ops/config/cache/service-api-defaults.yml · Purge: cascateado pelo brand worker |
| Browser localStorage | usuário | Logout 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.