Capítulo 1: Por que esta história importa?
Este estudo de caso parece um drama de tecnologia, mas ele mostra um ponto básico da vida profissional: engenharia é um trabalho coletivo. Um sistema de software não existe sozinho. Ele vive dentro de uma empresa, com pessoas, regras, prazos, custos e metas. Quando você entende isso, suas decisões técnicas ficam mais maduras.
Imagine o seguinte: na segunda-feira, um engenheiro otimiza um serviço crítico e reduz custos. Na terça-feira, ele é demitido. Isso parece injusto. Então por que aconteceu? A resposta tem pouco a ver com o código em si e muito a ver com governança, comunicação e risco.
Antes de continuar: alguns conceitos básicos
Microsserviço: pequeno sistema que faz uma função específica (ex: calcular um preço). Ele conversa com outros serviços por APIs.
API: interface de comunicação entre sistemas. Pense em um cardápio: você diz o que quer e recebe uma resposta padronizada.
Latência: quanto tempo um pedido leva para ser atendido. Menor latência = resposta mais rápida.
Throughput: quantos pedidos o sistema consegue atender por segundo.
Custo de nuvem: quanto a empresa paga por servidores, memória e tráfego.
Siglas e papéis que aparecem na história
SRE (Site Reliability Engineering): time focado em confiabilidade. Eles monitoram disponibilidade, incidentes e acordos de nível de serviço.
CTO (Chief Technology Officer): diretor de tecnologia. Decide estratégia técnica, padrões e investimentos de longo prazo.
CI/CD: pipelines automatizados que testam, validam e colocam código em produção com mais segurança.
ADR (Architecture Decision Record): documento curto que registra uma decisão arquitetural e seu motivo.
RFC (Request for Comments): documento aberto para debater uma proposta técnica antes de aprovar.
KPI: indicador de desempenho usado pela empresa para medir sucesso.
Agora vamos conhecer o serviço que gerou toda a confusão e as pessoas envolvidas.
Capítulo 2: Quem participa do sistema (e por que isso importa)
Em empresas reais, um sistema crítico não é tocado apenas por uma pessoa. Existem vários grupos que dependem dele. Cada grupo tem objetivos diferentes, é uma boa decisão técnica precisa equilibrar esses interesses.
- Time de Produto: quer entregar valor rápido para o cliente final.
- Time de Engenharia: quer manter o sistema limpo, testável e com baixa taxa de bugs.
- SRE/Operações: quer estabilidade, monitoramento e capacidade de resposta a incidentes.
- Segurança: quer reduzir vulnerabilidades, seguir políticas e auditorias.
- Liderança: quer previsibilidade de custo, prazo e risco.
Quando um engenheiro decide mudar tecnologia, ele impacta todos esses grupos. Por isso a empresa olha o problema de forma mais ampla do que apenas "está mais rápido?".
Capítulo 3: O sistema original, explicado do zero
O protagonista trabalhava em um serviço chamado Billing-Quotes (Cotações de Faturamento). Esse tipo de serviço recebe um pedido de outra parte do sistema, calcula valores e devolve um resultado. Parece simples, mas ele é usado por vários outros sistemas. Se ele parar, muita coisa para junto.
O ambiente técnico
- Linguagem: Java 21 com Spring Boot 3.x.
- Infraestrutura: 2 réplicas do serviço, cada uma com 2 vCPU e 4 GB de RAM.
- Uso: muitas requisições simultâneas, principalmente no horário do almoço.
Java é uma escolha comum em empresas grandes porque tem boa comunidade, muitas bibliotecas, ferramentas maduras e facilidade para contratar pessoas. Ele é confiável e previsível, o que ajuda na operação diária.
Qual era o problema?
O problema principal era latência inconsistente. Em horários de pico, algumas requisições ficavam lentas demais. O motivo eram pausas do Garbage Collector (GC).
Entendendo o Garbage Collector
Em Java, você cria objetos na memória o tempo todo. Depois que um objeto não é mais usado, o GC precisa limpar essa memória para liberar espaço. Ele faz isso automaticamente, mas, em alguns momentos, precisa pausar o programa para organizar tudo. Essa pausa é chamada de stop-the-world.
Essas pausas podem ser pequenas (milissegundos), mas em sistemas muito movimentados elas se acumulam e afetam a experiência do usuário final.
Como a equipe mede sucesso (SLOs)
O sistema tinha um objetivo de desempenho, chamado SLO (Service Level Objective). Ele dizia que o p95 das respostas deveria ficar abaixo de 120 ms.
O que é p95?
Pense em 100 requisições. Se ordenarmos do mais rápido ao mais lento, o p95 é a 95a requisição. Ele mostra o "pior caso normal".
E o p99? É a 99a requisição. Ele olha mais para a cauda extrema e ajuda a descobrir se alguns poucos usuários estão sofrendo muito.
Por que não usar a média?
A média esconde problemas. Uma requisição muito lenta pode estragar a experiência de um usuário, mesmo que a média pareça boa.
Medição e métricas: o que significa \"medir\" em software?
Medir em software não é apenas contar acessos. É transformar comportamento do sistema em números que ajudam a tomar decisões. Uma boa métrica responde a uma pergunta clara, como: \"Estamos melhorando o tempo de resposta?\" ou \"Os usuários estão encontrando erros?\"
Sem medição, qualquer decisão vira opinião. Com medição, você compara antes e depois, identifica tendências e justifica investimentos. É por isso que percentis como p95 e p99 são tão importantes: eles mostram o que acontece com os casos mais lentos, que costumam gerar reclamações.
SLI, SLO e SLA (siglas que andam juntas)
Essas três siglas aparecem sempre que falamos de confiabilidade. Elas parecem complicadas, mas são simples quando colocamos lado a lado:
- SLI (Service Level Indicator): a métrica em si (ex: p95 de latência).
- SLO (Service Level Objective): a meta para a métrica (ex: p95 < 120 ms).
- SLA (Service Level Agreement): o acordo formal com o cliente, com possíveis multas se a meta não for cumprida.
Em outras palavras: SLI é o que você mede, SLO é o que você quer, SLA é o que você promete.
Observabilidade: enxergar o sistema por dentro
Observabilidade é a capacidade de entender o que está acontecendo dentro do sistema apenas olhando para os sinais que ele emite. Em software, esses sinais aparecem em três pilares:
Métricas
Números agregados ao longo do tempo, como latência, throughput, uso de CPU e taxa de erros.
Logs
Registros detalhados de eventos. Servem para entender o que aconteceu em uma requisição específica.
Traces
Rastreamento de uma requisição através de vários serviços, mostrando cada etapa e seu tempo.
Por que observabilidade é um requisito de negócio?
Sem observabilidade, a empresa fica \"cega\". Um sistema pode estar lento e ninguém saber exatamente onde. Com observabilidade, a equipe responde mais rápido, reduz tempo de incidentes e evita perdas financeiras. Em ambientes de alta criticidade, isso separa uma operação madura de uma operação reativa.
Exemplo simples: a mesma falha com e sem observabilidade
Sem observabilidade: usuários reclamam, o time corre atrás do problema, cada pessoa verifica uma coisa diferente e o diagnóstico demora horas.
Com observabilidade: o alerta mostra que o p99 estourou, o trace indica um gargalo no banco de dados e o log confirma a consulta lenta. O time age em minutos.
Métricas essenciais para começar
- Latência: tempo de resposta (p50, p95, p99).
- Taxa de erro: porcentagem de respostas com falha (ex: 5xx).
- Throughput: requisições por segundo.
- Disponibilidade: quanto tempo o serviço ficou no ar.
Alertas: quando medir não basta
Medir é necessário, mas não suficiente. Você precisa de alertas que avisem quando algo saiu do normal. Bons alertas evitam \"falsos positivos\" e apontam o que realmente impacta o usuário.
Uma regra prática: alerte sobre impacto no usuário, não sobre detalhes internos. Exemplo ruim: \"CPU passou de 80%\". Exemplo bom: \"p95 passou do SLO por 10 minutos\".
Error budget (orçamento de erro)
Se o SLO diz que você pode falhar em 0,1% das requisições, isso vira um \"orçamento\" de erro. Enquanto houver orçamento, o time pode fazer mudanças rápidas. Quando o orçamento acaba, a prioridade vira estabilidade. É uma forma objetiva de equilibrar velocidade e confiabilidade.
Sintomas percebidos pelo negócio
- Clientes viam lentidão em horários específicos.
- O time de suporte recebia mais chamados.
- O custo de infraestrutura aumentava porque era preciso escalar mais máquinas.
O engenheiro olhou para isso e pensou: "Vou resolver na raiz". E aqui começa a virada da história.
Capítulo 4: A tentação do Rust, explicada passo a passo
Rust é uma linguagem de sistemas. Ela foi criada para ter alta performance e segurança de memória sem precisar de Garbage Collector. Isso soa perfeito para o problema descrito.
Por que Rust parecia a resposta ideal?
- Menos pausas: sem GC, não existem paradas longas do programa.
- Menos memória: Rust tende a usar menos memória do que Java em cargas altas.
- Desempenho previsível: mais fácil manter latência consistente.
Ownership e Borrowing (conceitos centrais do Rust)
Em Rust, cada valor tem um dono. Quando esse dono sai de escopo, a memória é liberada. Não existe coleta de lixo em segundo plano. O compilador impede erros de memória antes do programa rodar. Isso aumenta a confiabilidade, mas deixa o desenvolvimento mais rigoroso.
Rust no dia a dia: vantagens e custos
- Vantagem: performance alta e previsível.
- Vantagem: menos risco de problemas de memória.
- Custo: curva de aprendizado mais alta para novos desenvolvedores.
- Custo: menos ferramentas prontas dentro de algumas empresas.
O engenheiro decidiu reescrever o microsserviço em Rust. Tecnicamente, ele fez tudo certo.
O plano de execução (tecnicamente correto)
Resultados técnicos:
- p95 caiu de 118 ms para 94 ms.
- Memória reduziu em cerca de 45%.
- Custos de nuvem diminuíram.
Se a história fosse apenas técnica, terminaria aqui. Mas a empresa não é apenas técnica.
Capítulo 5: O julgamento corporativo
Quando o engenheiro apresentou o trabalho, ele foi confrontado por várias áreas. Cada uma via riscos que ele não considerou. Esse é o ponto central da história: engenharia não trabalha sozinha.
SRE: "Os números são bons, mas é estável em longo prazo?"
Gerente: "Quem vai manter isso quando você estiver de férias?"
Segurança: "Nossas ferramentas não analisam Rust."
CTO: "Qual é nossa política de linguagens?"
O problema não era o desempenho. O problema era governança. Empresas grandes priorizam previsibilidade e redução de risco. Mudar linguagem significa mexer em treinamento, suporte, segurança, custos e contratação.
O conceito de Bus Factor
Se apenas uma pessoa conhece um sistema crítico, o risco é alto. Caso ela saia, fique doente ou mude de área, a empresa perde capacidade de resposta. Ao usar Rust sem treinar o time, o engenheiro criou um bus factor igual a 1.
Os quatro erros fatais, detalhados
1. Otimizou o KPI errado
A liderança queria velocidade de desenvolvimento e facilidade de contratação. Ele entregou latência mais baixa, mas aumentou complexidade.
2. Criou dívida de ferramentas
Java já tinha pipelines de CI/CD, scanners de segurança e padrões de qualidade. Em Rust, isso precisava ser reconstruído.
3. Falha de comunicação
Mudanças grandes precisam de alinhamento. Sem avisar o time, ele isolou colegas e gerou resistência.
4. Confundiu refatoração com estratégia
Trocar a linguagem de um sistema core é uma decisão de negócio, não apenas técnica. Exige aprovação e planejamento de longo prazo.
Outros riscos invisíveis para iniciantes
- Onboarding: novos devs demoram mais para aprender Rust do que Java.
- Suporte 24/7: equipes de plantão precisam dominar o stack.
- Auditoria: áreas reguladas exigem ferramentas e evidências.
- Roadmap: mudar tecnologia consome tempo que poderia ser usado em novas features.
Capítulo 6: Como fazer do jeito certo
Se você realmente precisa mudar tecnologia em um sistema crítico, existe um caminho mais seguro. Ele é mais lento, mas reduz riscos e aumenta a chance de aprovação.
-
Comece com um sidecarEm vez de reescrever tudo, crie um pequeno componente em Rust apenas para a parte mais pesada (ex: parser de JSON). O serviço principal continua em Java.
-
Formalize a decisão (ADR ou RFC)Registre por escrito o problema, as opções e os riscos. Isso mostra maturidade e cria um histórico para futuras pessoas entenderem a escolha.
-
Traga Plataforma e Segurança para o inícioAntes de escrever o produto, alinhe com quem cuida dos pipelines, scanners e deploys. Assim, você não cria dívidas invisíveis.
-
Treine o time e aumente o bus factorNão basta você saber Rust. Pelo menos 3 ou 4 pessoas precisam conseguir depurar em produção.
-
Defina critérios de sucesso e o plano de volta"Se em 3 meses não reduzir custos em X, voltamos ao Java". Isso acalma a liderança.
Capítulo 7: Conclusões e reflexões
O engenheiro perdeu o emprego, mas conseguiu outro rapidamente. Para a empresa, o custo foi a incerteza. Para nós, fica a lição: boas decisões técnicas precisam de contexto.
Lição final
"O melhor engenheiro não é o que vence o benchmark;
e aquele que melhora sistemas sem surpreender a organização."
Checklist de sobrevivência (Go/No-Go)
Antes de propor uma nova tecnologia no seu estágio ou emprego, faça este checklist. Se não puder marcar todos, não faça.
- O problema de performance é real, medido e afeta o negócio.
- Existe suporte da equipe de Plataforma para segurança e deploy.
- Pelo menos 4 pessoas sabem debugar esse código em produção.
- Existe um botão de desfazer que funciona em minutos.
- A liderança aprovou explicitamente a mudança de estratégia.