Desenvolvedor backend Perguntas de Entrevista & Respostas

As entrevistas de desenvolvedor backend testam seu entendimento de arquitetura do lado do servidor, design de bancos de dados, desenvolvimento de APIs e escalabilidade de sistemas. Espere perguntas sobre modelagem de dados, concorrência, segurança e sistemas distribuídos.

Perguntas comportamentais

  1. 1. Conte-me sobre uma ocasião em que precisou depurar um problema complexo em produção.

    Resposta modelo

    Nossa API começou a retornar erros 500 de forma intermitente, afetando cerca de 5% das requisições, mas somente nos horários de pico. Os logs mostravam timeouts de conexão com o banco de dados, embora CPU e memória do banco estivessem normais. Adicionei monitoramento do pool de conexões e descobri que estávamos esgotando o limite do pool (20 conexões). A causa raiz: uma nova funcionalidade abria uma transação no banco, fazia uma chamada HTTP a um serviço externo dentro da transação e esse serviço às vezes demorava mais de 30 segundos para responder, mantendo a conexão do banco presa. Resolvi reestruturando o código para fazer a chamada HTTP fora da transação e abrindo a conexão somente para a escrita no banco. Aumentei também o tamanho do pool para 50 como margem de segurança e configurei alertas sobre a utilização do pool. A taxa de erros 500 caiu para zero imediatamente.

  2. 2. Descreva uma situação em que projetou uma API consumida por outras equipes. Como garantiu que ela fosse fácil de usar para desenvolvedores?

    Resposta modelo

    Projetei uma API de integração com parceiros que 15 empresas externas usariam para sincronizar dados de produtos com nossa plataforma. Antes de escrever qualquer código, realizei entrevistas com 5 potenciais consumidores da API para entender seus padrões de integração. Aprendi que precisavam de operações em lote (não apenas CRUD registro a registro) e queriam webhooks para atualizações em tempo real. Projetei a API com convenções de nomenclatura consistentes, paginação, filtragem e respostas de erro detalhadas com mensagens práticas: não apenas '400 Bad Request', mas '400: O campo preço deve ser um número positivo. Recebido: -5,99.' Gerei documentação OpenAPI a partir do código, criei um ambiente de sandbox com dados de teste e escrevi um guia de início rápido com exemplos em Python, Node.js e curl. Também versionei a API desde o primeiro dia (v1 no caminho da URL). O resultado: o tempo médio de integração foi de 3 dias, contra uma média do setor de 2 semanas, e os tickets de suporte foram 70% menores do que na versão anterior da API.

  3. 3. Conte-me sobre uma migração de banco de dados que você liderou e que foi particularmente desafiadora.

    Resposta modelo

    Precisávamos migrar 500 milhões de linhas de um banco MySQL monolítico para PostgreSQL mantendo a aplicação em funcionamento: zero downtime era um requisito rígido. Elaborei uma abordagem em fases. Fase 1: configurar o PostgreSQL com o novo schema e implementar escrita dupla (dual-write), ou seja, a aplicação escreve nos dois bancos simultaneamente. Fase 2: preencher os dados históricos com um script de migração em lote que processava 100 mil linhas por hora nos horários de menor tráfego, com checksums para verificar a integridade dos dados. Fase 3: transferir gradualmente o tráfego de leitura para o PostgreSQL usando uma feature flag, começando com 5% e aumentando ao longo de 2 semanas enquanto monitorávamos discrepâncias. Fase 4: quando 100% das leituras estavam no PostgreSQL sem alertas de discrepância, desativamos as escritas no MySQL e descomissionamos o banco antigo. A migração completa levou 6 semanas. Identificamos 3 bugs de inconsistência de dados durante a fase de leitura dupla que teriam causado problemas em produção numa migração big-bang.

  4. 4. Dê-me um exemplo de como você melhorou a segurança de um sistema backend.

    Resposta modelo

    Conduzi uma auditoria de segurança do nosso sistema de autenticação e encontrei vários problemas: tokens JWT com expiração de 30 dias, refresh tokens armazenados em localStorage (vulnerável a XSS) e limitação de taxa aplicada apenas aos endpoints de login. Implementei uma revisão de segurança abrangente: reduzi a expiração do JWT para 15 minutos com refresh silencioso, movi os refresh tokens para cookies HTTP-only seguros com SameSite=Strict, implementei limitação de taxa por janela deslizante em todos os endpoints autenticados (100 requisições por minuto por usuário), adicionei assinatura de requisição para operações sensíveis (transferências, alterações de senha) e implementei log de auditoria para todos os eventos de autenticação. Configurei também varredura automatizada de vulnerabilidades de dependências com Snyk no pipeline de CI. Após a implementação, passamos num teste de penetração de terceiros sem nenhuma descoberta crítica ou de alta gravidade, contra 4 descobertas críticas na auditoria anterior.

Perguntas técnicas

  1. 1. Explique o teorema CAP e como ele influencia a escolha de banco de dados.

    Resposta modelo

    O teorema CAP afirma que um armazenamento de dados distribuído pode garantir no máximo duas das três propriedades: Consistência (toda leitura retorna o dado mais recente), Disponibilidade (toda requisição recebe uma resposta) e Tolerância a partições (o sistema continua operando apesar de falhas de rede entre nós). Como partições de rede são inevitáveis em sistemas distribuídos, a escolha real é entre consistência e disponibilidade durante uma partição. Sistemas CP (como PostgreSQL com replicação síncrona, MongoDB, HBase) se recusam a responder em vez de retornar dados desatualizados, adequados para sistemas financeiros onde dados incorretos são piores do que a indisponibilidade. Sistemas AP (como Cassandra, DynamoDB, CouchDB) sempre respondem, mas podem retornar dados desatualizados, adequados para feeds de redes sociais, catálogos de produtos ou camadas de cache onde consistência eventual é aceitável. Na prática, escolho com base no custo do erro: se dados desatualizados causam prejuízo financeiro ou problemas de segurança, opto por CP. Se uma breve desatualização é invisível para os usuários, opto por AP para maior disponibilidade e menor latência.

  2. 2. Como você projetaria um sistema de limitação de taxa (rate limiting)?

    Resposta modelo

    Avaliaria quatro algoritmos conforme o caso de uso. Janela fixa: conta requisições em intervalos de tempo fixos (por exemplo, 100 por minuto). Simples, mas permite rajadas nas fronteiras da janela: um usuário poderia fazer 100 requisições às 0:59 e mais 100 à 1:00. Log de janela deslizante: registra o timestamp de cada requisição e conta as requisições na janela anterior. Preciso, mas consome muita memória para APIs de alto volume. Contador de janela deslizante: híbrido entre janela fixa e deslizante, usa a contagem da janela anterior ponderada pela sobreposição de tempo. Boa precisão com baixo uso de memória. Token bucket: tokens se acumulam a uma taxa fixa e cada requisição consome um token. Permite rajadas controladas mantendo a taxa média. Essa é minha escolha padrão por ser intuitiva, lidar bem com picos de tráfego e ser simples de implementar. Para a implementação: Redis com INCR e EXPIRE para limitação de taxa distribuída, com o formato de chave sendo user_id:endpoint:janela. Retornaria cabeçalhos de limite de taxa (X-RateLimit-Remaining, X-RateLimit-Reset) para que os clientes possam se autorregular, e usaria respostas HTTP 429 com um cabeçalho Retry-After.

  3. 3. O que são índices de banco de dados e quando utilizá-los?

    Resposta modelo

    Um índice é uma estrutura de dados (geralmente B-tree ou hash) que acelera a recuperação de dados ao custo de escritas mais lentas e armazenamento adicional. É como o índice de um livro: em vez de ler todas as páginas para encontrar um tópico, você o consulta no índice e vai direto à página certa. Use índices em: colunas nas cláusulas WHERE (especialmente em tabelas grandes), colunas de JOIN, colunas usadas em ORDER BY e colunas com alta cardinalidade (muitos valores únicos). Evite índices em: tabelas pequenas (o scan sequencial é mais rápido), colunas com baixa cardinalidade (booleanas, campos de status com 3 valores), colunas atualizadas com frequência (overhead de manutenção do índice) ou tabelas com muita escrita onde o desempenho de leitura não é crítico. Índices compostos importam: um índice em (user_id, created_at) ajuda consultas que filtram por ambos os campos, ou apenas por user_id, mas não apenas por created_at. Uso EXPLAIN ANALYZE para verificar se as consultas realmente utilizam os índices criados: o planejador de consultas às vezes ignora índices quando estima que um scan sequencial é mais rápido.

  4. 4. Como você gerencia transações de banco de dados em uma arquitetura de microsserviços?

    Resposta modelo

    Transações ACID tradicionais não funcionam entre microsserviços porque cada serviço possui seu próprio banco de dados. A solução padrão é o padrão Saga: uma sequência de transações locais em que cada etapa publica um evento que aciona a próxima, e cada etapa tem uma transação compensatória para rollback. Há duas abordagens: coreografia (serviços reagem a eventos de forma autônoma) e orquestração (um coordenador central gerencia o fluxo). Prefiro orquestração para fluxos complexos porque a lógica fica em um único lugar e é mais fácil de depurar. Exemplo: processar um pedido envolve o serviço de Pedidos (criar pedido), o serviço de Pagamento (cobrar o cartão) e o serviço de Estoque (reservar estoque). Se o pagamento falhar, o orquestrador chama a transação compensatória do serviço de Pedidos para cancelar o pedido. Se o estoque falhar após o pagamento ser aprovado, o orquestrador reembolsa o pagamento e cancela o pedido. Considerações importantes: idempotência é fundamental (cada etapa deve suportar ser chamada duas vezes), transações compensatórias devem ser confiáveis e você precisa de observabilidade sobre o estado da saga para depurar fluxos com falha.

Perguntas situacionais

  1. 1. Sua API está sofrendo um pico de tráfego 10 vezes acima do normal, degradando o desempenho. Que medidas você toma?

    Resposta modelo

    Imediato (primeiros 15 minutos): ativar cache agressivo no CDN ou reverse proxy para endpoints com alto volume de leitura. Ativar auto-scaling dos servidores de aplicação se ainda não estiver em execução. Verificar se o banco de dados é o gargalo: se sim, habilitar réplicas de leitura para requisições GET e adicionar pool de conexões (PgBouncer para PostgreSQL). Curto prazo (próxima hora): implementar throttling de requisições para endpoints não críticos a fim de proteger os caminhos essenciais. Adicionar uma fila para escritas que podem ser processadas de forma assíncrona (eventos de análise de usuário, notificações por e-mail). Considerar um circuit breaker nas chamadas a serviços externos que possam estar causando falhas em cascata. Se o tráfego for esperado (momento viral, lançamento de produto): escalar horizontalmente, adicionar camadas de cache e otimizar as consultas mais pesadas ao banco. Se for inesperado (possível DDoS): verificar os padrões de tráfego, habilitar limitação de taxa por IP e considerar regras de WAF. Após o pico: realizar uma revisão de capacidade para definir gatilhos de scaling que lidem com isso automaticamente na próxima vez.

  2. 2. Você precisa adicionar uma funcionalidade que exige alterações em uma tabela de banco de dados muito utilizada, com bilhões de linhas. Como você aborda essa mudança de schema?

    Resposta modelo

    Nunca execute ALTER TABLE diretamente em uma tabela com um bilhão de linhas em produção: isso bloqueará a tabela por horas. Eu usaria uma ferramenta de migração de schema online como pt-online-schema-change (MySQL) ou pg_repack (PostgreSQL), que cria uma cópia sombra da tabela, aplica a alteração, sincroniza os dados com triggers e faz a troca das tabelas com bloqueio mínimo. Para adicionar uma coluna: adicione-a como anulável primeiro (rápido, sem reescrita da tabela), preencha os dados em lotes durante os horários de menor tráfego (processe 10 mil linhas por lote com um intervalo de 100ms entre os lotes) e então adicione a restrição NOT NULL se necessário após o preenchimento completo. Para alterar o tipo de uma coluna: crie uma nova coluna com o tipo de destino, escreva nos dois simultaneamente durante a migração, preencha a nova coluna, altere as leituras da aplicação para a nova coluna e então descarte a coluna antiga. Os princípios-chave: cada etapa deve ser reversível, a migração deve ocorrer em segundo plano sem bloqueio e a aplicação deve funcionar corretamente em cada estado intermediário.

  3. 3. Uma API de terceiros da qual o seu serviço depende começa a retornar erros em 50% das chamadas. Como você lida com isso?

    Resposta modelo

    Primeiro, implementar um padrão circuit breaker. Após N falhas consecutivas (digamos, 5), abrir o circuito: parar de chamar a API e retornar uma resposta de fallback (dados em cache, valores padrão ou uma mensagem de degradação graciosa) durante um período de resfriamento. Após o resfriamento, permitir uma única requisição de teste. Se for bem-sucedida, fechar o circuito e retomar a operação normal. Segundo, adicionar lógica de retry com backoff exponencial para falhas transitórias: tentar novamente após 1s, depois 2s, depois 4s, com jitter para evitar o efeito thundering herd. Terceiro, implementar uma fila de requisições para que operações que dependam dessa API possam ser tentadas novamente se falharem. Quarto, alertar a equipe e verificar a página de status do provedor. Se o problema persistir, considere armazenar respostas em cache de forma mais agressiva, criar um fallback para um provedor alternativo ou enfileirar requisições para processamento em lote durante períodos estáveis. A longo prazo: para qualquer dependência crítica de terceiros, mantenha um acordo de nível de serviço documentado e uma estratégia de fallback definida antes do primeiro incidente.

  4. 4. Você é solicitado a construir um sistema de notificações que envie e-mails, notificações push e SMS. Como você arquitetaria isso?

    Resposta modelo

    Eu o projetaria como um sistema orientado a eventos com três camadas. Primeira, a camada de requisição de notificação: serviços publicam eventos de notificação em uma fila de mensagens (RabbitMQ ou SQS) com um payload independente do canal, contendo destinatário, tipo de notificação, nome do template e variáveis do template. Isso desacopla o remetente da mecânica de entrega. Segunda, a camada de orquestração: um serviço de notificação consome os eventos, consulta as preferências do usuário (quais canais ele habilitou), resolve os templates e publica mensagens específicas por canal em filas separadas (fila de e-mail, fila de push, fila de SMS). Terceira, a camada de entrega: workers específicos por canal consomem de sua fila e chamam o provedor adequado (SendGrid para e-mail, FCM/APNS para push, Twilio para SMS). Cada worker gerencia retries, limitação de taxa e lógica específica do provedor de forma independente. Decisões de design importantes: chaves de idempotência para evitar envios duplicados, um log de notificações para auditoria e depuração, armazenamento de preferências do usuário para opt-out e seleção de canal e versionamento de templates para que possamos atualizá-los sem reimplantar o código. Implementaria também uma dead letter queue para notificações com falha permanente, com alertas configurados.

Dicas para a entrevista

Para perguntas de design de sistemas, sempre clarifique os requisitos primeiro. Prepare-se para escrever código: endpoints de API, consultas SQL ou implementações de algoritmos. Mostre que pensa nos modos de falha.

Pratique estas perguntas com IA

Experimente uma entrevista simulada grátis

Pratique estas perguntas com IA

Perguntas frequentes

Como se preparar para uma entrevista backend?
Estruturas de dados e algoritmos, design de bancos de dados, design de API (princípios REST, autenticação), design de sistemas (escalabilidade, cache, filas de mensagens) e o modelo de concorrência da sua linguagem principal.
Qual a importância do design de sistemas?
Crítico para cargos intermediários e sênior. Espere pelo menos uma rodada dedicada a projetar um sistema.
Devo conhecer múltiplas linguagens?
Expertise profunda em uma é melhor que conhecimento superficial de muitas. Conheça o ecossistema da sua linguagem principal a fundo.
Como as entrevistas backend diferem das de software engineer?
Focam mais em design de bancos de dados, arquitetura de API e escalabilidade do lado do servidor.

Cargos relacionados

Artigos relacionados

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