Engenheiro de Software Perguntas de Entrevista & Respostas

As entrevistas de engenharia de software avaliam competências amplas: da resolução de problemas de código ao design de sistemas, passando por como você colabora sob pressão. Este guia cobre as perguntas comportamentais, técnicas e situacionais mais comuns em processos seletivos de startups a grandes empresas de tecnologia no Brasil, com respostas de exemplo baseadas no método STAR.

Perguntas comportamentais

  1. 1. Conte sobre uma vez em que você discordou de uma decisão técnica tomada pelo seu time. Como você lidou com isso?

    Resposta modelo

    Na empresa anterior, o time queria adotar um banco NoSQL para uma funcionalidade que na verdade tinha consultas relacionais complexas, com múltiplos joins entre pedidos, pagamentos e estoque. Eu achava que um banco relacional seria mais adequado para esse padrão de acesso. Em vez de simplesmente discordar em voz alta na reunião, preparei um documento curto comparando as duas abordagens nos nossos padrões de consulta reais, com exemplos concretos de queries que precisaríamos escrever em cada modelo. Levei isso para a próxima revisão de design e propusemos rodar um spike de uma semana testando as duas opções com dados reais de produção anonimizados. Os números do spike confirmaram minha recomendação: a versão relacional era 3 vezes mais rápida nas consultas mais frequentes. O time mudou de abordagem sem constrangimento, porque a decisão se apoiou em dados concretos apresentados de forma objetiva. O aprendizado principal foi que evidência concreta facilita que as pessoas mudem de ideia sem perder a compostura.

  2. 2. Descreva um projeto em que você precisou aprender uma tecnologia nova rapidamente, sob pressão de prazo.

    Resposta modelo

    Tínhamos três semanas para lançar uma funcionalidade de acompanhamento de pedidos em tempo real que exigia WebSockets, algo que eu nunca tinha usado em produção antes. Organizei minhas manhãs para estudo focado: construí um protótipo descartável primeiro, li a documentação da biblioteca que usaríamos e depois analisei como projetos open source maiores tratavam casos extremos, como reconexão e ordenação de mensagens fora de sequência. Também pareei com um colega que já tinha experiência com WebSockets para revisar meu código antes de cada merge. Entregamos no prazo e a funcionalidade não teve nenhum incidente em produção no primeiro trimestre após o lançamento. O que aprendi foi que aprender sob pressão funciona melhor quando você constrói algo pequeno e descartável antes de tentar entender a teoria completa: a prática dá contexto para a leitura.

  3. 3. Dê um exemplo de uma vez em que você melhorou significativamente a performance de um sistema.

    Resposta modelo

    Nossa API voltada para o cliente tinha latência de 800ms no percentil 95. Fiz o profiling dos endpoints mais lentos e encontrei três padrões de consulta N+1 na camada de ORM. Reescrevi essas consultas com joins explícitos e adicionei um cache Redis para uma consulta de permissões de usuário que era lida com muita frequência e alterada raramente. A latência caiu para 120ms no p95. Convencer o time a investir o tempo necessário foi a parte mais difícil: construí um painel simples que ligava diretamente a latência à taxa de conversão no checkout, o que tornou o argumento de negócio óbvio para todo mundo, inclusive para quem não é técnico.

  4. 4. Conte sobre um projeto em que você trabalhou que falhou. O que você fez?

    Resposta modelo

    Lançamos uma funcionalidade de recomendação de vagas que levou dois meses para construir e teve engajamento próximo de zero. Otimizamos para taxa de clique, mas os usuários achavam as sugestões irrelevantes para o momento de carreira deles. Conduzi um post-mortem e identificamos a causa raiz: nunca conversamos com usuários reais antes de construir. Escrevi um resumo de uma página com os aprendizados e propus adicionar uma etapa de descoberta com entrevistas de usuário ao nosso processo de desenvolvimento de funcionalidades. Essa mudança de processo durou muito mais do que a funcionalidade em si: hoje temos uma etapa consistente de entrevista com usuários antes de qualquer construção relevante, e o time trata isso como não negociável.

Perguntas técnicas

  1. 1. Explique como você projetaria um encurtador de URLs como o bit.ly.

    Resposta modelo

    No núcleo, você precisa de duas operações: escrita (dada uma URL longa, retornar um código curto) e leitura (dado um código curto, redirecionar para a URL original). Para o código curto, eu usaria codificação Base62 de um ID autoincremental, o que dá cerca de 3,5 bilhões de códigos com 6 caracteres. O caminho de escrita grava no banco de dados e armazena o mapeamento em cache. O caminho de leitura é cache-first, com fallback para o banco de dados. Em escala, leituras superam escritas em muitas ordens de grandeza, então a taxa de acerto do cache é o fator crítico de performance. Eu adicionaria limitação de taxa nas escritas para evitar abuso, e armazenaria data de criação, ID do usuário e analytics de cliques em uma tabela separada, para manter o caminho de leitura enxuto e rápido.

  2. 2. Qual é a diferença entre um processo e uma thread? Quando você usaria um em vez do outro?

    Resposta modelo

    Um processo é um programa independente em execução, com seu próprio espaço de memória isolado. Uma thread é uma unidade de execução mais leve dentro de um processo, compartilhando memória com outras threads do mesmo processo. Uso threads quando as tarefas precisam se comunicar com frequência e compartilhar estado: são mais baratas de criar e trocar de contexto. Uso processos quando preciso de isolamento: se um cair, os outros continuam rodando. Na prática, recorro a threads para paralelismo ligado a CPU dentro de um único serviço, e a processos quando preciso de isolamento de memória ou de rodar serviços separados. Em Python, o GIL faz com que threads não entreguem paralelismo real de CPU, então multiprocessing costuma ser a escolha certa para trabalho pesado de CPU nessa linguagem.

  3. 3. Explique o conceito de consistência eventual. Dê um exemplo de quando você aceitaria esse modelo.

    Resposta modelo

    Consistência eventual significa que um sistema distribuído vai retornar o mesmo valor para uma chave em todos os nós, mas não necessariamente de forma imediata. As escritas se propagam de forma assíncrona, então leituras feitas logo após uma escrita podem retornar dados desatualizados por um curto período. Eu aceitaria consistência eventual para casos como contadores de curtidas em redes sociais, sincronização de preferências do usuário entre dispositivos ou atualização de estoque em um catálogo de e-commerce, onde ficar levemente desatualizado por um ou dois segundos não causa dano real. Eu não aceitaria esse modelo para transações financeiras, tokens de autenticação ou qualquer situação em que dados desatualizados possam gerar um resultado de negócio incorreto ou um problema de segurança, como em transferências via Pix, onde o saldo precisa refletir o estado real no momento da confirmação.

  4. 4. Como funciona a coleta de lixo (garbage collection) em uma linguagem que você conhece bem? Quais são os trade-offs?

    Resposta modelo

    Em Java, a JVM usa um coletor de lixo geracional. O heap é dividido em gerações jovem e antiga, de acordo com o tempo de vida dos objetos. A maioria dos objetos morre jovem, então o coletor roda GCs menores e baratos com frequência na geração jovem. Objetos que sobrevivem a várias coletas são promovidos para a geração antiga, coletada com menos frequência, mas de forma mais custosa. Os coletores G1 e ZGC minimizam pausas de stop-the-world fazendo a maior parte do trabalho de forma concorrente. O trade-off é overhead de memória e latência de pausa imprevisível: a coleta de lixo essencialmente troca throughput por gerenciamento automático de memória. Em sistemas sensíveis a latência já ajustei tamanhos de heap e configurações de GC e, em casos extremos, movi alocações do caminho quente para fora do heap para evitar a pressão de coleta por completo.

Perguntas situacionais

  1. 1. Você está no meio de uma sprint quando descobre uma vulnerabilidade de segurança crítica em uma biblioteca da qual seu sistema depende. O que você faz?

    Resposta modelo

    Primeiro avalio a severidade e a exploitabilidade: essa vulnerabilidade está sendo explorada ativamente e o nosso padrão de uso da biblioteca nos expõe? Se sim, escalo imediatamente para o tech lead e o time de segurança, e tratamos isso como incidente, não como tarefa normal de sprint. Procuro primeiro uma versão corrigida da biblioteca. Se não existir, verifico se conseguimos mitigar no nosso próprio código enquanto esperamos o patch, ou se faz sentido trocar de biblioteca. Comunico o status com clareza: quem é afetado, qual é o risco, o que estamos fazendo e qual é o prazo. O escopo da sprint muda como consequência: a correção da vulnerabilidade entra primeiro, mesmo que isso signifique adiar outras entregas planejadas para a sprint seguinte.

  2. 2. Você é designado para uma base de código legada, sem testes e sem documentação. Precisa adicionar uma funcionalidade significativa. Como você aborda isso?

    Resposta modelo

    Não mexo em nada antes de entender o comportamento atual. No primeiro dia, mapeio os pontos de entrada do código, o fluxo de dados e as dependências principais, rodando o sistema localmente e rastreando requisições pelo código. Antes de escrever qualquer código novo, adiciono testes de caracterização nas áreas que preciso alterar: testes que capturam o comportamento atual, não o comportamento ideal. Esses testes viram minha rede de segurança. Depois faço as menores mudanças possíveis para adicionar a funcionalidade, com testes unitários adequados para o código novo. Resisto à vontade de refatorar tudo que me incomoda: isso é uma conversa separada com o time, com seu próprio prazo e avaliação de risco, e não deve ser misturada com a entrega da funcionalidade pedida.

  3. 3. Seu time está discutindo duas abordagens arquiteturais. O engenheiro sênior prefere uma abordagem que você considera excessivamente complexa. Como você lida com isso?

    Resposta modelo

    Primeiro garanto que entendi completamente a abordagem dele antes de contestar: às vezes a complexidade existe por boas razões que eu ainda não enxerguei. Faço perguntas para entender as restrições que ele está otimizando. Se depois disso eu ainda achar que minha abordagem é melhor, escrevo uma comparação breve: os trade-offs de cada opção, o que ganhamos e o que perdemos em cada uma, e minha recomendação com a justificativa. Apresento como 'é assim que estou vendo, estou deixando passar alguma coisa?', em vez de simplesmente afirmar que estou certo. Se, depois da discussão, o engenheiro sênior ainda preferir a abordagem dele, eu me comprometo com ela e executo bem: divergências arquiteturais merecem um bom debate, não uma discussão contínua que trava o time inteiro.

  4. 4. Pedem para você estimar quanto tempo uma funcionalidade vai levar, mas os requisitos ainda não estão claros. O que você faz?

    Resposta modelo

    Eu não dou um número único para um escopo pouco claro: esse número vai sair errado e depois eu vou ser cobrado por ele. Em vez disso, faço perguntas de esclarecimento para entender o requisito principal e identificar as incertezas de maior risco. Depois dou uma faixa: 'com base no que sei hoje, isso é de 3 a 5 dias, mas essas três perguntas em aberto podem levar o prazo para 2 semanas.' Deixo claro o que preciso para reduzir a estimativa: uma decisão sobre o comportamento de um caso extremo, acesso a um sistema específico ou um dia para investigar a parte que não conheço bem. Boas estimativas nascem de uma conversa, não de um prazo tirado do ar.

Dicas para a entrevista

Pense em voz alta durante os problemas técnicos: o processo importa tanto quanto a solução final. Para perguntas comportamentais, prepare de 5 a 6 histórias fortes da sua experiência que possam se adaptar a diferentes tipos de pergunta. Se você não souber uma resposta, diga isso e mostre como chegaria a ela.

Pratique estas perguntas com IA

Experimente uma entrevista simulada grátis

Pratique estas perguntas com IA

Perguntas frequentes

Quanto tempo duram as entrevistas de engenheiro de software?
A maioria dos processos seletivos de engenheiro de software dura de 2 a 4 semanas e inclui de 3 a 4 etapas: triagem com recrutador, uma entrevista técnica, e uma etapa final com o time sobre design de sistemas e questões comportamentais. Em empresas de produto é comum uma conversa adicional com a liderança técnica.
Quais linguagens de programação devo usar em uma entrevista de engenharia de software?
Use a linguagem que você domina melhor. A maioria dos entrevistadores aceita Python, Java, C++, JavaScript ou Go. Python é comum em entrevistas pela sintaxe concisa. A linguagem importa menos do que sua capacidade de escrever código limpo e correto e explicar seu raciocínio com clareza.
Qual a importância do design de sistemas em uma entrevista de engenharia de software?
Para vagas de nível pleno e sênior, design de sistemas costuma ser a parte mais decisiva do processo. Os entrevistadores avaliam sua capacidade de pensar em escala, fazer trade-offs e comunicar ideias complexas. Para vagas júnior, design de sistemas aparece menos, mas entender conceitos básicos como bancos de dados, APIs e cache continua sendo valioso.
Como devo me preparar para perguntas comportamentais como engenheiro de software?
Prepare de 5 a 6 histórias fortes da sua experiência usando o método STAR (Situação, Tarefa, Ação, Resultado). Cubra temas como conflito com um colega, uma falha e o que você aprendeu com ela, uma vez em que tomou iniciativa e um projeto do qual você tem orgulho. Essas histórias podem se adaptar para responder muitas perguntas comportamentais diferentes.

Cargos relacionados

Artigos relacionados

Usamos cookies para analisar o tráfego do site, medir nossa publicidade e melhorar sua experiência. Você pode alterar suas preferências a qualquer momento. Cookie Policy