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.
Problema
AiUsageGuardmantém os contadores de uso diário em umEnumMapem memória: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 comreplicas > 1), cada pod tem seu próprio mapa independente.Consequência
Se
OPENAI_MAX_IMAGES_PER_DAY=10e 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.javaSolução sugerida
Duas abordagens sem aumentar escopo:
Opção 1 (mínima): Documentar explicitamente no
application.ymlque 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 umSELECT FOR UPDATEpara 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.