Engenharia de Software & Carreira

Engenharia Não Trabalha Sozinha

Um estudo de caso profundo sobre decisões técnicas, governança corporativa e por que reescrever código nem sempre é a solução.

Baseado na história real "I Rewrote A Java Microservice In Rust And Lost My Job" de Noah Byteforge.

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?

  1. Menos pausas: sem GC, não existem paradas longas do programa.
  2. Menos memória: Rust tende a usar menos memória do que Java em cargas altas.
  3. 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)

Em vez de substituir tudo de uma vez, ele colocou o novo serviço em paralelo. O tráfego era desviado aos poucos por uma feature flag. Se algo desse errado, bastava desligar a flag e voltar ao Java.

Logs, métricas e rastreamento do novo serviço foram configurados para se parecer com os do antigo. Assim, o time de operação podia comparar e monitorar sem mudar tudo de lugar.

Ele criou testes automatizados, comparou resultados com o sistema antigo e garantiu que um rollback seria feito em minutos, não em horas.

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.

  1. Comece com um sidecar
    Em 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.
  2. 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.
  3. Traga Plataforma e Segurança para o início
    Antes de escrever o produto, alinhe com quem cuida dos pipelines, scanners e deploys. Assim, você não cria dívidas invisíveis.
  4. Treine o time e aumente o bus factor
    Não basta você saber Rust. Pelo menos 3 ou 4 pessoas precisam conseguir depurar em produção.
  5. 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.