One Door to the Models, Parte 5: Identidade, Quota e Chargeback
São cinco dimensions por métrica, e as time series se multiplicam. A Parte 5 constrói identidade de tenant, quota e chargeback que sobrevive à cardinalidade.

O design do chargeback é decidido por um limite do Azure Monitor, não por uma preferência contábil: uma métrica custom permite 10 dimension keys, o API Management já gasta 5 delas em defaults, e as time series ativas que uma policy produz são o produto dos valores únicos de cada dimension que você adiciona. Três dimensions com dez valores cada são mil time series, contra um teto de 50.000 time series ativas por região por subscription em uma janela de doze horas. Coloque um user ID ou um request ID nessa métrica e a telemetria da própria plataforma vira o incidente. A Parte 4 concluiu os três caminhos de requisição. Esta parte responde a pergunta pela qual a série inteira existe: qual time gastou o quê, e como o gateway impede que um deles gaste a quota de todos os outros.
Duas credenciais, dois trabalhos diferentes
O API Management oferece dois mecanismos que as pessoas rotineiramente tratam como alternativas quando na verdade são complementares.
Uma subscription key identifica um consumidor para fins de products, quotas e analytics. Ela chega no header Ocp-Apim-Subscription-Key, ou em um query parameter subscription-key que só é verificado quando o header está ausente, e ambos os nomes são configuráveis por API. As keys são emitidas em pares para que uma aplicação possa migrar da key A para a key B e regenerar a A com o mínimo de interrupção.
Duas coisas sobre keys precisam ser tratadas como decisão de design em vez de assumidas como resolvidas. Primeiro, o API Management não tem lifecycle embutido para subscription keys: sem data de expiração, sem rotação automática. Rotação é um workflow que você constrói, com Azure PowerShell ou os SDKs, e se você não construir, as keys vivem para sempre. Segundo, a key é repassada ao backend por default, onde pode acabar nos logs de monitoramento do backend e em qualquer lugar para onde esses logs forem enviados. Um set-header no fim da seção inbound que a remove é uma correção de duas linhas para um achado de credencial-em-logs que, de outra forma, é descoberto por um auditor.
Um JWT do Microsoft Entra ID responde a uma pergunta diferente: este chamador está autorizado agora. Ele expira nativamente, pode ser revogado centralmente e carrega claims. As aplicações obtêm um por meio do flow OAuth2 client credentials, e o gateway o valida antes de qualquer outra coisa rodar:
<validate-jwt header-name="Authorization" require-scheme="Bearer"
require-expiration-time="true" require-signed-tokens="true"
clock-skew="60"
output-token-variable-name="jwt"
failed-validation-httpcode="401"
failed-validation-error-message="Invalid or missing token.">
<openid-config url="https://login.microsoftonline.com/{{tenant-id}}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://genai-gateway</audience>
</audiences>
<required-claims>
<claim name="roles" match="any">
<value>model.invoke</value>
</claim>
</required-claims>
</validate-jwt>
output-token-variable-name é a parte que justifica o próprio lugar: o token validado cai em uma variável de policy, então policies posteriores podem ler um claim dele em vez de confiar em um header que o chamador controla. Isso importa imediatamente, porque a próxima decisão é qual valor serve de chave para a quota.
A armadilha do acesso anônimo
Vale dizer com todas as letras porque a configuração que produz isso parece inofensiva. Se uma API pode ser chamada sem nenhuma subscription key depende de duas configurações independentes: se a própria API exige uma subscription, e se todo product ao qual ela está atribuída exige uma. Se a API não exige subscription, chamadas sem key são permitidas no contexto da API mesmo quando uma key com escopo de product também funcionaria. O gateway está fazendo exatamente o que lhe disseram; ninguém lhe disse a intenção.
Para um gateway na frente de capacidade paga de modelo, a regra é que toda API exige uma subscription e todo product exige uma subscription, e a policy validate-jwt roda de qualquer forma, então uma chamada não autenticada falha duas vezes. Os escopos das keys também importam: uma key com escopo de serviço ou de todas as APIs abre todas as APIs da instância, o que é certo para o ferramental do próprio time de plataforma e errado para um consumidor. Consumidores recebem keys com escopo de product.
Quota, e contra o que contá-la
A policy de limite de tokens da Parte 1 recebe um counter-key, e essa escolha é o modelo de tenancy inteiro. Usar o subscription ID como chave dá um bucket por consumidor, que é o que o incidente da Parte 1 precisava: o batch job de marketing não consegue drenar a quota do assistente de clientes porque são subscriptions diferentes com counters diferentes.
<llm-token-limit counter-key="@(context.Subscription.Id)"
tokens-per-minute="{{tpm_tier}}"
estimate-prompt-tokens="true"
remaining-tokens-variable-name="remainingTokens"
remaining-tokens-header-name="x-remaining-tokens" />
Devolver a franquia restante em um response header vale os dois atributos extras. Um cliente que consegue ver a própria folga pode recuar antes de receber um 429, e uma conversa de suporte sobre throttling começa de um número que os dois lados conseguem ver.
Os products viram os tiers: um product interativo com limite alto por minuto e uma quota diária modesta, um product de batch com o inverso, e um product sandbox com limites baixos o suficiente para que um loop descontrolado em um notebook seja um incômodo em vez de um incidente. Um tenant é uma aplicação do Entra ID mais uma ou mais subscriptions de product, provisionadas pelo Terraform da camada 30-tenants da Parte 2, nunca por um ticket.
O orçamento de dimensions
Agora a restrição do lead, declarada como a regra de design que ela produz. O Azure Monitor limita métricas custom a 10 dimension keys, e o API Management usa 5 delas para defaults, incluindo Region, Service ID, Service Name e Service Type. Isso deixa no máximo 5 dimensions custom por policy. O limite maior é combinatório: as time series ativas equivalem ao produto dos valores únicos entre as suas dimensions no período, então três dimensions com dez valores cada contribuem com mil, e o teto regional é de 50.000 time series ativas por subscription em doze horas. Múltiplas instâncias de API Management na mesma região contribuem para o mesmo total regional.
A consequência é uma divisão limpa que vale escrever na documentação da própria plataforma:
- Métricas carregam apenas dimensions de baixa cardinalidade. Tenant, alias de modelo, environment. Três dimensions, conjuntos de valores limitados, dashboards que carregam rápido e alertas que disparam na coisa certa.
- Logs carregam todo o resto. Request ID, user ID se ele for capturado, tamanhos de prompt e completion, latência, qual backend atendeu. Application Insights e Log Analytics são onde a atribuição por requisição vive, e o job mensal de chargeback os consulta.
<llm-emit-token-metric namespace="llm-metrics">
<dimension name="Tenant" value="@(context.Subscription.Name)" />
<dimension name="ModelAlias" value="@(context.Request.MatchedParameters.GetValueOrDefault("model","unknown"))" />
<dimension name="Environment" value="{{env}}" />
</llm-emit-token-metric>
Três dimensions, deliberadamente. A quarta que alguém vai pedir é user ID, e a resposta é não: ela pertence ao registro de log, onde cardinalidade custa storage em vez do orçamento de métricas de uma região inteira.
Chargeback que sobrevive a uma discussão com o financeiro
O job mensal é engenharia de dados comum, e sua credibilidade repousa em ser explícito sobre a exatidão, não em parecer preciso. As Partes 3 e 4 estabeleceram três classes, e o documento de chargeback as nomeia:
- Síncrono sem streaming: medido a partir do
usagedo próprio modelo. Exato. - Síncrono com streaming: tokens de prompt e completion estimados no gateway, porque streaming força estimativa independentemente da configuração de policy. Aproximado, com o desvio acompanhado como métrica própria.
- Batch: exato, a partir das contagens de requisição do próprio job e do usage por resposta no arquivo de saída, porque o control plane o submeteu.
O job produz um número por tenant e uma linha de reconciliação: a soma do gasto atribuído contra o custo real do recurso no período. Um resíduo de poucos por cento, estável mês a mês, é o custo honesto da estimativa. Um resíduo que cresce é um bug, na maioria das vezes um chamador que encontrou um caminho por fora do gateway. Publicar o resíduo em vez de escondê-lo é o que torna o resto do número crível, e ele também funciona como detector do caminho de bypass sobre o qual a Parte 1 alertou.
Quando um time precisa do próprio gateway
Ocasionalmente os requisitos de um consumidor não cabem em infraestrutura compartilhada: um workload regulado que precisa do próprio isolamento de rede, ou um time que deve gerenciar as próprias APIs sem tocar nas de mais ninguém. Os workspaces do API Management existem para isso, e a escolha é entre o managed gateway default do serviço, disponível nos tiers v2 sem custo extra de gateway e com acesso às capacidades embutidas, e um workspace gateway separado, disponível em Basic v2, Standard v2, Premium e Premium v2, que compra isolamento forte de runtime e scaling, hostname e configuração de rede independentes, ao preço de custo extra, deployment mais demorado e suporte em menos regiões.
Um detalhe decide se isso é reversível: a configuração de virtual network de um workspace gateway só pode ser definida quando o gateway é criado, e não pode ser alterada depois. Sua configuração de rede também é independente da configuração da instância de API Management. Um workspace gateway criado sem isolamento, por um time que depois precisa dele, é um rebuild.
Modos de falha para observar
- Uma dimension de alta cardinalidade em uma policy. Ela não vai dar erro. Ela vai consumir em silêncio o orçamento de time series ativas da região, e o primeiro sintoma são as métricas custom de outros times deixando de aparecer.
- Keys que nunca expiram. Não existe expiração ou rotação embutida. Sem um workflow de rotação, a credencial emitida para uma aplicação desativada continua funcionando, e nada reporta isso.
- A subscription key nos logs do backend. O comportamento default a encaminha. Remova-a no inbound, e cheque os logs do backend uma vez para confirmar em vez de assumir.
- Uma API que não exige subscription. Acesso anônimo no contexto da API, alcançado por uma configuração que se lê como permissiva em vez de aberta.
- Chargeback publicado sem o próprio resíduo. Na primeira vez que um product owner encontra uma discrepância que você não divulgou, todo número futuro vira negociável.
O que a Parte 6 herda
Tenants com identidades reais, quotas que se sustentam, e um número mensal por time com uma exatidão declarada. O que arma a próxima pergunta com precisão: o token mais barato é o que nunca foi enviado, e semantic caching é o primeiro mecanismo desta série que reduz a fatura em vez de apenas atribuí-la. Ele também muda em silêncio o que os números acima significam, porque um cache hit é uma requisição que não custou nada e ainda assim precisa aparecer no relatório de alguém.
Leia isso a seguir
- Parte 6, Semantic Caching e Seus Modos de Falha, onde o token mais barato se torna aquele que nunca é enviado, e o mecanismo que faz isso vira uma superfície de correção.
- Parte 4, Trabalho Assíncrono Fora do Caminho da Requisição, onde a contabilidade de batch da qual este modelo de chargeback depende foi construída.
- Sua Conta de LLM É um Problema de Observabilidade, a versão geral do argumento de atribuição, antes de qualquer gateway específico.
Para o lado de infraestrutura e plataforma de rodar isso em escala, as notas de campo estão em ercan.cloud, e o hub fica em ercanermis.com.
Referências
Mais de Ercan
Mais dois sites, mesmo autor, terreno diferente.
Cloud, AWS, EKS, Terraform, engenharia de plataforma.
Notas de campo de sistemas em produção. EKS, IAM, Terraform em escala organizacional, observabilidade, otimização de custos.
Visitar ercan.cloud →O hub. Sobre, consultoria, contato.
Hub pessoal para as duas trilhas de escrita. Quem sou eu, como funciona a consultoria, como me contatar.
Visitar ercanermis.com →