Skip to content

[Backend] AiUsageGuard com estado em memória não funciona em múltiplas réplicas #137

Description

@muniagebot

Problema

AiUsageGuard mantém os contadores de uso diário em um EnumMap em memória:

private final Map<AiOperation, Integer> dailyUsage = new EnumMap<>(AiOperation.class);

Com o uso de synchronized, o controle funciona corretamente dentro de um único processo. Porém, em um ambiente com múltiplas réplicas (K8s com replicas > 1), cada pod tem seu próprio mapa independente.

Consequência

Se OPENAI_MAX_IMAGES_PER_DAY=10 e o deployment tiver 3 réplicas, o limite efetivo passa a ser 30 chamadas por dia (10 por pod), tornando o controle de custo ineficaz.

Localização

src/main/java/br/com/munif/stella/api/service/AiUsageGuard.java

Solução sugerida

Duas abordagens sem aumentar escopo:

Opção 1 (mínima): Documentar explicitamente no application.yml que os limites são por instância, e ajustar os valores considerando o número de réplicas. Adicionar comentário no código.

Opção 2 (robusta): Persistir os contadores na tabela metricas_consulta_vetorial (já existe) ou em uma tabela dedicada no PostgreSQL, usando um SELECT FOR UPDATE para garantir atomicidade. Isso remove a dependência de estado em memória e funciona com qualquer número de réplicas.

Contexto atual

O deployment atual usa replicas: 1, então o problema não se manifesta. Mas é uma armadilha para quem quiser escalar o deployment horizontalmente — o comportamento seria silenciosamente incorreto.

Contexto de aula

Excelente exemplo de problema de estado distribuído: mostrar o que muda quando se passa de 1 para N réplicas e por que estado em memória não é confiável em sistemas cloud-native.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendk8sKubernetes / infraestrutura de produçãosecurityVulnerabilidade ou hardening de segurançatriage:futuroBoa ideia, mas futura ou sem prioridade para a estrutura atualtriage:superflua-agoraSupérflua para a estrutura atual, especialmente no Gimli

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions