Cache SWR GraphQL (NestJS, code-first)
Visão Geral
Armazene em cache por intenção, não por mecanismo. Um único formato de política, um único fluxo de eventos observável, um único rastreamento por requisição. Monte no nível do serviço por padrão; escale para campo / operação / transporte apenas quando medido.
Três verdades difíceis que moldam cada decisão:
- Apollo Server não possui stale-while-revalidate nativo. Seu
responseCachePluginé apenas TTL e no nível de operação. SWR real vem da sua própria camada (async-cache-dedupeoumercurius-cacheno driver Mercurius) ou de um CDN. - Escopo padrão é
public. Uma entrada pública é compartilhada literalmente por todos os chamadores, portanto, só é correta quando o resultado é byte-idêntico para todos eles. No momento em que um valor varia por chamador, ele deve ser marcado comoperUser— ou vaza. - Interceptors do Nest não envolvem métodos de serviço, e o
CacheInterceptordo@nestjs/cache-managernão funciona em GraphQL. Portanto, o decorador de nível de serviço que você deseja é um wrapper de método sobre um motor de deduplicação — não um interceptor do framework.
Quando Usar
- GraphQL NestJS (code-first) onde resolvedores/serviços acessam repetidamente um banco de dados ou API externa.
- Você precisa eliminar picos de latência e debandadas na expiração do TTL (SWR verdadeiro).
- Você precisa raciocinar sobre segurança de cache multi-usuário / vazamento.
- Você precisa de visibilidade sobre decisões de acerto / stale / falta.
- Você precisa desligar o cache completamente — dev, CI ou um incidente — com uma única flag (veja Seção 1,
setup-disable-switch). - Você está configurando a capacidade de cache em um aplicativo pela primeira vez (veja Seção 1).
Quando NÃO usar:
- Você já está atrás de um CDN fazendo cache de resposta para tráfego GET/APQ público — comece por lá.
- Caminhos de escrita/mutação, ou dados por usuário sem reuso e com baixa amplificação de leitura (cache adiciona risco para pouco ganho).
O Contrato de Callback
key, @CacheTag e @InvalidateTags aceitam funções. Acertar seus argumentos ou o cache
falha silenciosamente e as tags falham silenciosamente em purgar.
| Callback | Assinatura | O que args é |
|---|---|---|
key | (args, ctx) => unknown[] | Promise<unknown[]> | a lista de argumentos do método, na ordem de chamada — args[0], nunca args.id |
@CacheTag | (result, args) => string[] | null | a mesma lista; result é o valor de retorno do método |
@InvalidateTags | (result, args) => string[] | a mesma lista; result é o valor de retorno da escrita |
- Posicional, não nomeado. Para
getTitle(id: string), o id éargs[0]. - Resultado vem primeiro em ambos os callbacks de tag. O
referencesdo motor bruto é(args, key, result)— ordem diferente, primeiro argumento diferente (vejadriver-async-cache-dedupe). ctx(userId,tenantId,locale, maisgen) é derivado da requisição e montado porbuildCacheContext; está vazio fora de uma requisição, então um job passa o que precisa como argumento.- Tipagem: os padrões são
unknown[]/unknown— anote a tupla (@Cacheable<[string]>,@CacheTag<[string]>) ou os corpos dos callbacks não compilarão. - Nível de campo é diferente: lá
argsé o objeto de argumento nomeado do resolvedor ectxé o contexto GraphQL (driver-mercurius-cache).
Contrato completo, o pacote de chave { a, k, u } e os casos extremos de serialização:
policy-key-derivation. Implementação em tempo de execução: setup-decorator-runtime.
Categorias de Regras por Prioridade
| Prioridade | Categoria | Impacto | Prefixo |
|---|---|---|---|
| 1 | Configuração Única | CRÍTICO | setup- |
| 2 | Política de Cache | CRÍTICO | policy- |
| 3 | Segurança contra Vazamento | CRÍTICO | safety- |
| 4 | Invalidação | ALTO | invalidation- |
| 5 | Observabilidade | MÉDIO | observability- |
| 6 | Drivers | MÉDIO | driver- |
Referência Rápida
1. Configuração Única (CRÍTICO)
setup-decorator-runtime- Implementar os Decoradores como Wrappers de Método com Nomes Estáveissetup-disable-switch- Enviar um Único Switch de Configuração que Ignora o Cache de Nível de Serviçosetup-engine-choice- Usar um Motor de Deduplicação e Contar TTL em Segundossetup-fail-open- Falhar Aberto e Nunca Armazenar Erros em Cachesetup-file-placement- Posicionar a Capacidade por Quem a Importasetup-identity-context- Ler o Chamador de AsyncLocalStorage, Não de Scope.REQUESTsetup-module-wiring- Conectar o Módulo de Cache uma Vez com forRootAsyncsetup-storage-and-invalidation- Habilitar Invalidação e Definir referencesTTL e GC
2. Política de Cache (CRÍTICO)
policy-five-knobs- Conhecer os Cinco Botõespolicy-key-derivation- Derivar a Chave Automaticamente, Nunca com JSON.stringifypolicy-mount-at-service- Montar no Nível de Serviço por Padrãopolicy-one-writing-pattern- Os Decoradores São o Único Padrão de Escritapolicy-service-escape-hatch- A API de Serviço é uma Válvula de Escape, Não um Segundo Padrão
3. Segurança contra Vazamento (CRÍTICO)
safety-default-public- Escopo Padrão é Público — Marcar Leituras que Variam por Chamador como perUsersafety-key-dimensions- Escopo Cobre Apenas o Usuário — Todas as Outras Dimensões Vão na Chavesafety-no-leak-checklist- Executar a Lista de Verificação Sem Vazamento em Toda Leitura em Cache
4. Invalidação (ALTO)
invalidation-after-success- Invalidar Apenas Após uma Escrita Bem-Sucedidainvalidation-atomic-purge- Purgar Atomicamente e Limitar a Cardinalidade de Tagsinvalidation-generation-prefix- Usar um Prefixo de Geração para Domínios Grandes ou Genéricosinvalidation-tags-purge-only- Tags São Apenas para Purga, Nunca para Consulta
5. Observabilidade (MÉDIO)
observability-limits-of-events- Saber o que o Motor Não Pode Reportarobservability-metrics-and-tests- Rastrear as Métricas que Comprovam a Correção e Testar Resultadosobservability-per-request-trace- Expor um Rastreamento por Requisição, Apenas em Dev no GraphQLobservability-structured-events- Emitir Eventos de Cache Estruturados, Não Strings de Log
6. Drivers (MÉDIO)
driver-apollo-response-cache- Opção C — Apollo responseCachePlugin (Nível de Operação, Apenas TTL)driver-apollo-vs-mercurius- Escolher a Opção de Nível de Campo a partir do Seu Driverdriver-async-cache-dedupe- Opção A — async-cache-dedupe (Nível de Serviço, Independente de Transporte)driver-cdn-transport- Opção E — Transporte / CDN SWR (Apenas Leituras Públicas)driver-envelop-response-cache- Opção D — Envelop useResponseCache (Não Nativo do NestJS)driver-federation-router- Apenas Federation — Cache de Resposta do Apollo Routerdriver-mercurius-cache- Opção B — mercurius-cache (Nível de Campo, SWR Real)driver-version-pinning- Fixar Versões — Esta Área Muda
Como Usar
Comece pela seção de Configuração Única, depois leia as regras de política, segurança e invalidação
para a decisão que você tem pela frente. Os arquivos de regras ficam em rules/:
rules/setup-module-wiring.md
rules/_sections.md
Cada arquivo de regra contém:
- O que é a regra e a falha que ela previne
- Um exemplo incorreto com explicação
- Um exemplo correto com explicação
- Referências
Documento Compilado Completo
Para o guia completo com todas as regras expandidas em um único documento, veja AGENTS.md.