Uma aplicação de produção começou a devolver erros de autenticação para usuários reais.
O primeiro impulso foi procurar uma queda de servidor, um processo travado ou algum problema no banco.
Nada disso tinha acontecido.
Os servidores estavam ativos. Os processos estavam rodando. O container continuava respondendo ao health check.
Mesmo assim, a operação estava parcialmente parada.
O teste que parecia inofensivo
Durante uma atividade normal de desenvolvimento, foi gerado um novo login contra um ERP externo.
A integração usava tokens de sessão fornecidos por esse ERP. A aplicação mantinha esses tokens em cache para não precisar autenticar a cada chamada.
O detalhe perigoso era que desenvolvimento e produção usavam a mesma credencial externa.
O fornecedor não tratava cada ambiente como uma identidade isolada. Um novo login podia invalidar ou deslocar uma sessão que a produção ainda estava usando.
Poucos minutos depois, a aplicação começou a receber respostas equivalentes a “login ou senha inválido” em várias operações do ERP.
O erro aparecia em massa, para usuários diferentes. Isso era um sinal importante: não era um registro específico nem um problema isolado de usuário. Era a autenticação da aplicação contra a dependência externa.
O servidor estava saudável
Esse tipo de incidente é perigoso porque os indicadores tradicionais continuam verdes.
O processo não caiu. O container não reiniciou. O endpoint de health check respondeu. O banco continuou disponível.
Mas a função principal da integração estava quebrada.
Em uma ocorrência, usuários perceberam o problema rapidamente e abriram chamados. Em outra, o erro ficou silencioso por dias. Os jobs continuavam executando, mas uma etapa importante retornava zero registros. Como não havia um alerta para esse resultado de negócio, a infraestrutura continuava reportando saúde.
Essa diferença merece uma definição explícita:
Saúde técnica significa que o sistema está executando.
Saúde operacional significa que ele está entregando o resultado esperado.
Uma não garante a outra.
A cadeia causal
O incidente não tinha uma única causa isolada. Ele era uma cadeia de decisões razoáveis que, combinadas, criaram um risco grande:
- Ambientes diferentes compartilhavam uma credencial externa.
- O fornecedor tinha regras de sessão concorrente que não estavam sob nosso controle.
- A aplicação reutilizava um token em cache e não tinha recuperação automática confiável.
- O token existia em mais de um lugar, como arquivo de ambiente, CI e Secret Manager.
- O deploy podia recriar configurações antigas.
- O health check verificava o processo, não a integração crítica.
- Os jobs não tinham alerta específico para volume de resultado inesperadamente zerado.
O primeiro incidente sugeriu que o fornecedor permitia apenas uma sessão por credencial. Testes posteriores indicaram uma hipótese mais cuidadosa: poderia existir um limite ou pool pequeno de sessões, com invalidação dos tokens mais antigos quando novas sessões eram criadas.
O tamanho exato desse limite não foi provado. Para a operação, porém, o efeito era o mesmo: gerar sessões novas contra uma credencial compartilhada podia derrubar uma sessão ainda usada pela produção.
Essa distinção é importante. Uma boa análise não transforma uma hipótese conveniente em fato só porque ela explica o primeiro sintoma.
O conserto emergencial
A recuperação imediata foi operacional:
- Gerar tokens novos usando credenciais de autenticação mais estáveis.
- Validar esses tokens contra endpoints reais antes de aplicá-los.
- Atualizar as configurações do ambiente legado, do CI e do ambiente em nuvem.
- Reiniciar os processos para que carregassem os valores novos.
- Observar chamadas bem-sucedidas durante um período de estabilização.
Isso restaurou o serviço, mas ainda era um band-aid. Trocar o valor de um segredo não remove o risco de ele ser revogado novamente.
Também havia um problema de distribuição. Atualizar apenas o .env do servidor não bastava se o próximo deploy recriasse o arquivo a partir de um parâmetro antigo do CI.
A correção estrutural
O desenho da correção precisava eliminar a dependência de intervenção manual:
1. Separar ambientes de verdade
Desenvolvimento, homologação e produção precisam de credenciais externas diferentes sempre que o fornecedor permitir.
Quando isso não for possível, a restrição deve ser tratada como um risco formal, com procedimento de diagnóstico e controles explícitos.
2. Reautenticar automaticamente
A aplicação não deve depender indefinidamente de um token de sessão salvo no ambiente. Quando o token expira ou é rejeitado, o sistema precisa obter outro de maneira controlada.
3. Compartilhar o cache entre processos
Um cache em memória cria uma sessão diferente para cada processo. Com vários workers, cron e containers, a própria aplicação pode gerar sessões demais.
Um cache compartilhado reduz esse comportamento e torna o estado da autenticação visível para todos os processos.
4. Coordenar a reautenticação
Se vários processos perceberem o token inválido ao mesmo tempo, todos podem tentar fazer login. Isso cria uma nova rajada de sessões justamente no momento em que o sistema está se recuperando.
Um lock distribuído permite que apenas um processo faça a reautenticação. Os demais aguardam o novo token aparecer no cache compartilhado.
5. Monitorar o resultado do negócio
O health check precisa responder perguntas além de “o processo está vivo?”
- A autenticação com o ERP está funcionando?
- A última importação trouxe registros dentro do esperado?
- A fila recebeu itens quando deveria?
- A taxa de erro da dependência externa mudou abruptamente?
Nem toda checagem precisa ser uma chamada pesada em produção. Métricas de resultado, idade do último sucesso e alertas de volume anormal já capturam uma classe importante de falhas silenciosas.
O que esse incidente ensinou
O erro mais fácil de apontar seria o login manual. Ele foi o gatilho de uma ocorrência, mas não explica sozinho por que a produção era vulnerável.
O risco real estava na combinação de:
- credencial compartilhada;
- sessão externa com regras pouco conhecidas;
- token sem renovação automática;
- configuração replicada em vários lugares;
- monitoramento sem visão do resultado operacional.
Esse padrão aparece em muitos contextos. Pode ser um ERP, uma API bancária, um gateway de pagamentos ou qualquer fornecedor que use sessões, tokens e limites próprios.
Quando uma integração é crítica, disponibilidade não pode ser medida apenas pelo estado do servidor.
Checklist para evitar o mesmo problema
- Use credenciais distintas por ambiente.
- Nunca gere login de desenvolvimento contra uma credencial de produção.
- Documente se o fornecedor limita sessões ou invalida tokens antigos.
- Tenha refresh ou reautenticação automática.
- Use cache compartilhado quando houver múltiplos processos.
- Coordene a recuperação com lock distribuído.
- Mantenha uma fonte única para secrets e parâmetros de deploy.
- Alimente alertas com métricas de negócio.
- Teste também o caminho de falha da dependência externa.
- Diferencie health check técnico de health check operacional.
A aplicação estava saudável. O negócio estava parado.
O objetivo da arquitetura e da operação é garantir que essas duas frases nunca mais possam ser verdadeiras ao mesmo tempo.
Top comments (0)