Póster "Pasos para resolver un problema" | profe.social
Como resolver problemas técnicos sem perder a sanidade
A maioria das pessoas encara um problema técnico com a abordagem errada desde o início. Elas leem o erro, tentam a primeira solução que encontram no Google e torcem para que funcione. Isso raramente funciona, especialmente em sistemas complexos onde múltiplos fatores se conectam de formas inesperadas. O que funciona é um processo mais lento e menos glamoroso do que os tutoriais mostram.
resolva o problema: o método que ninguém quer ouvir
A primeira coisa que você precisa fazer é entender o que está acontecendo antes de tentar consertar qualquer coisa. Isso parece óbvio, mas é onde a maioria das pessoas falha. Quando eu comecei a trabalhar com infraestrutura de rede há anos atrás, lidava com um problema recorrente de latência em servidores na AWS que aparecia apenas entre 14h e 16h em dias de semana. Passamos três semanas testando configurações, trocando instâncias, ajustando balanceadores — até perceber que era um job de backup do PostgreSQL rodando em paralelo com consultas pesadas de reporting no mesmo RDS. A solução foi mover o cron para as 3h da madrugada. Três semanas porque ninguém parou para perguntar o que estava acontecendo no sistema naquele horário.
O processo básico funciona assim: isole a variável, observe o comportamento, formule uma hipótese, teste, registre o resultado. Repita até que o problema desapareça ou você descubra que não era o que pensava. E na maioria das vezes, não era.
O que todo mundo erra na resolução
O erro mais comum é atacar o sintoma em vez da causa. Você vê um serviço caindo, reinicia ele, e pronto, problema resolvido, certo? Errado. O serviço caiu por um motivo, e se você não descobrir esse motivo, ele vai cair de novo no próximo ciclo. Reiniciar um container ou serviço é como tirar um remédio para dor de cabeça quando a causa é uma infecção renal. Alivia, mas não cura.
Outro erro grave é confiar na primeira mensagem de erro que aparece. Os logs são seus amigos, mas eles muitas vezes mentem ou pelo menos omitem informações críticas. Um erro de timeout pode significar um problema de rede, um problema de configuração, um problema no banco de dados, ou um problema no código da aplicação. O timeout é o sintoma. A causa pode estar em qualquer uma dessas camadas. Eu já perdi um dia inteiro debuggando um certificado SSL que não expirava até descobrir que o problema era um regra de firewall bloqueando a renovação automática do Let's Encrypt no host errado. O log dizia "certificate expired", mas o certificado estava perfeitamente válido.
Técnicas avançadas que fazem diferença
O method of isolation é a técnica mais poderosa que existe para resolver problemas complexos. Você remove componentes um por um até o problema desaparecer, e aí sabe qual deles era o culpado. Funciona melhor quando você tem um ambiente de staging que replica a produção. Se não tem, crie um, mesmo que rudimentar. Tentar isolar variáveis em produção é uma receita para desastre.
Outra técnica subestimada é o reverse engineering do estado. Em vez de perguntar o que causou o problema, pergunte o que era diferente entre o estado funcionando e o estado quebrado. Alterações recentes são o maior preditor de problemas. Um deploy, uma atualização de package, uma mudança de configuração — qualquer coisa que tenha mudado no último dia ou dois merece atenção prioritária. Eu fiz uma lista mental chamada "coisas que mudaram recentemente" e comecei por aí sempre que algo quebrou. Achei a causa raiz de cerca de 70% dos problemas só com esse passo.
Quando o método falha
Existem cenários onde o método científico de resolução de problemas simplesmente não funciona bem. Problemas de performance em larga escala, por exemplo, muitas vezes têm causas não determinísticas. Um gargalo que aparece apenas sob carga específica pode ser impossível de reproduzir em ambiente controlado. Nesses casos, a melhor abordagem é monitoramento contínuo e observabilidade, não debugging reativo. Ferramentas como Prometheus com Grafana, ou soluções como Datadog e New Relic, permitem que você visualize padrões ao longo do tempo em vez de reagir a incidentes isolados.
Problemas de concorrência e race conditions também são notoriamente difíceis. Eles aparecem de forma intermitente, dependem de timing exato, e frequentemente não se repetem da mesma maneira. Para esses, logging estruturado com tracing distribuído (OpenTelemetry é o padrão atual) é essencial. Sem IDs de request rastreáveis entre serviços, você está essencialmente cego.
Um exemplo prático
Recentemente precisei resolver um problema onde uma API REST retornava 500 erros intermitentemente em um serviço Node.js rodando em containers Kubernetes. O log do aplicativo não mostrava nada anômalo. O código parecia correto. A primeira coisa que fiz foi verificar o estado dos containers: memória, CPU, conexões de rede. Tudo dentro do normal. A segunda coisa foi olhar os métricas do cluster: nenhum pod sendo restartado, nenhum OOM kill. Aí notei algo que não tinha visto antes — os erros aconteciam em picos sincronizados com requisições de outro serviço que fazia chamadas batch para o mesmo endpoint.
O problema era que o serviço tinha um limite de conexões de banco de dados configurado para 50, mas o batch do outro serviço consumia todas as conexões durante os picos, deixando zero disponíveis para as requisições normais. A solução não era aumentar o pool de conexões (isso apenas adia o problema), mas sim implementar fila de rate limiting entre os dois serviços com Redis como buffer. Resolvi o problema em duas horas depois de identificar o padrão. Passei seis horas apenas identificando o padrão.
O que aprendi com anos de experiência
A coisa mais importante sobre resolver problemas técnicos não é o conhecimento técnico em si. É a disciplina de não pular etapas. Cada minuto que você gasta entendendo o problema corretamente economiza horas de tentativa e erro. A segunda coisa é manter registros. Um arquivo simples com datas, sintomas, ações tomadas e resultados — isso vira um banco de dados pessoal de resolução de problemas que você consultará repetidamente. Eu encontrei soluções para problemas atuais em notas que fiz anos atrás para problemas aparentemente não relacionados.
A terceira coisa é saber quando pedir ajuda. Alguns problemas exigem perspectiva externa porque você ficou cego pelos próprios suposições. Colocar o problema em palavras para outra pessoa frequentemente revela a resposta. Esse é o princípio do rubber duck debugging, e funciona porque forçar a articulação do problema exige que você o processe de forma mais estruturada.