Capítulo 102 de 456

use cache: remote

Core Idea

'use cache: remote' armazena o output em um cache handler remoto (ex. Redis/KV) em vez de em memória, dando cache durável e compartilhado entre todas as instâncias do servidor. Use quando o use cache in-memory sofre com evicção, restrição de memória ou não persiste entre requests/restarts, ao custo de infraestrutura e latência de rede.

Key Concepts

  • Handler configurável: implementação vem via cacheHandlers; provedores de hosting normalmente fornecem automaticamente, self-hosted precisa configurar.
  • Quando evitar: já existe key-value store próprio na frente dos dados; operações já rápidas (<50ms); cache keys quase todas únicas por request (filtros de busca); dados mudam a cada segundos/minutos.
  • Quando faz sentido: conteúdo fora do static shell (componente lê cookies()/headers()/searchParams dentro de Suspense); APIs com rate limit; backends lentos; operações caras; serviços instáveis.
  • Cache key deve minimizar dimensões únicas: cachear por category em vez de por price filter, ou por language em vez de por userId, aumenta a taxa de hit.
  • Regras de nesting: remote pode aninhar dentro de remote ou de use cache normal; remote e use cache: private NUNCA podem se aninhar entre si (nos dois sentidos).
  • Não persiste entre deploys: cache key inclui buildId/deploymentId, então build novo invalida tudo (mesma regra do use cache).

Code Examples

import { connection } from 'next/server'
import { cacheLife, cacheTag } from 'next/cache'

async function getGlobalStats() {
  'use cache: remote'
  cacheTag('global-stats')
  cacheLife({ expire: 60 }) // 1 minute

  const stats = await db.analytics.aggregate({
    total_users: 'count',
    active_sessions: 'count',
    revenue: 'sum',
  })

  return stats
}
  • O que demonstra: cache remoto compartilhado para uma query cara, garantindo no máximo 1 request/minuto ao banco independente de quantos usuários acessem o dashboard; connection() força deferimento para request time antes da chamada cacheada.

Reference Tables

Featureuse cache'use cache: remote''use cache: private'
Server-side cachingIn-memory ou cache handlerRemote cache handlerNone
Cache scopeShared across all usersShared across all usersPer-client (browser)
Pode acessar cookies/headers diretoNoNoYes
Server cache utilizationPode ser baixa fora do static shellAlta (compartilhada entre instâncias)N/A
Custo adicionalNoneInfraestrutura (storage, network)None
Persiste entre deploysNoNoN/A
Deployment OptionSupported
Node.js serverYes
Docker containerYes
Static exportNo
AdaptersYes

Anti-patterns

  • Cachear por dimensão de alta cardinalidade (ex. price filter, userId): derruba a taxa de hit; cacheie pela dimensão de poucos valores únicos (categoria, idioma) e filtre o resto em memória.
  • Aninhar use cache: remote dentro de use cache: private (ou vice-versa): erro, essa combinação nunca é válida.
  • Usar remote cache para dado por-usuário: prefira use cache: private; remote é para dado compartilhado entre usuários.
  • Usar remote cache quando operação já é rápida (<50ms) ou local: a latência de lookup remoto pode piorar em vez de melhorar.

Key Takeaways

  1. Remote cache resolve o problema de baixa taxa de hit do use cache in-memory em ambientes serverless/fora do static shell.
  2. Escolha a dimensão certa da cache key: menos valores únicos = mais reuso.
  3. As três directives de cache (use cache, use cache: remote, use cache: private) podem ser combinadas na mesma página, cada uma para o tipo certo de dado (estático, compartilhado-runtime, por-usuário).
  4. connection() é o mecanismo explícito para forçar deferimento a request time sem precisar ler cookies/headers.

Connects To

  • use cache (ch100): base para entender cache keys e cacheLife/cacheTag.
  • use cache: private (ch101): alternativa para dado específico do usuário.