O problema
A Decisiv mantém uma plataforma em que montadoras, concessionárias e frotas de caminhões gerenciam eventos de serviço: um caminhão chega à oficina, um orçamento é escrito, a frota aprova, o reparo é feito e faturado. Essas empresas têm sistemas próprios e precisavam ler e gravar esses dados sem entrar em uma aplicação web.
A plataforma já tinha uma API REST pública, mas adicionar recursos exigia coordenação entre implementação, documentação e permissões. A validação de entrada vivia em classes avulsas de “extrair e validar” sem regras compartilhadas, a documentação OpenAPI era editada à mão e descolava do código, e as permissões de um endpoint novo eram um passo manual separado e fácil de esquecer. Alguns endpoints de listagem também precisavam de trabalho de performance sob cargas maiores.
O que eu fiz
Sou um dos engenheiros responsáveis pela camada de API. Nos últimos anos minha parte tem sido: desenhar e entregar recursos novos, o trabalho de performance nos endpoints lentos, a documentação OpenAPI e os dashboards e monitores que avisam o time quando algo regride.
Como resolvi
Validação contract-first. Todo endpoint agora começa com um contrato dry-validation que declara os parâmetros, seus tipos e as regras entre campos. O contrato é escrito e testado antes de o controller existir, e o controller só roda quando o contrato passa. Regras compartilhadas (paginação, sparse fieldsets, sintaxe de filtro) ficam em macros reutilizáveis, então dois endpoints não conseguem validar a mesma coisa de jeitos diferentes.
Três mudanças coordenadas por recurso. Um recurso novo sai como três pull requests revisados juntos: a API em si, a especificação OpenAPI no repositório dela e a semente de permissões que diz à camada de autorização quais perfis podem chamar o endpoint. Sem a terceira um cliente real recebe um erro de pré-condição, então o padrão torna impossível não perceber o bug da “permissão esquecida”.
Banco primeiro na performance. Investigo endpoints lentos separando consultas repetidas de associações do custo da consulta principal. Esse trabalho inclui ler planos de execução, conferir estimativas e índices disponíveis, e comparar alternativas de consulta com dados representativos. O carregamento antecipado de associações e as mudanças na consulta principal são avaliados separadamente.
Observabilidade. Os logs de requisição carregam a aplicação OAuth, o tenant, o endpoint e o tempo, então dashboards no Datadog e no LogScale mostram uso e taxa de erro por parceiro e por endpoint. Os monitores acionam em mudanças de taxa de erro e latência, não em limites fixos.
O que foi difícil
Escopo multi-tenant. O mesmo endpoint atende frotas, concessionárias e patrocinadores, e um filtro correto para um formato de conta é errado para outro. Acertar a política exigiu ler como cada chamador se relaciona com os dados, não só quem ele é.
Distinguir um N+1 real de uma regressão de plano. Os dois aparecem como “o endpoint está lento”, e as correções não têm nada em comum. Hoje sempre pego um plano de consulta em um ambiente com dados parecidos com produção antes de mexer no código da aplicação.
O resultado
O trabalho de performance reduziu a latência dos endpoints envolvidos. Recursos novos saem com documentação e permissões na mesma release, e o checklist de revisão é o próprio padrão. Dashboards por parceiro fazem com que um problema de integração de um cliente geralmente apareça antes de ele escrever.
Onde conferir
A documentação pública para desenvolvedores está no link abaixo. O código é privado. Um artigo separado neste site usa um exemplo fictício para explicar como investigo o comportamento do planejador de consultas.