dezembro 21, 2025
12 min de leitura

Perguntas Node.js para entrevista backend sênior

interview
career-advice
job-search
Perguntas Node.js para entrevista backend sênior
Milad Bonakdar

Milad Bonakdar

Autor

Prepare-se para entrevistas backend sênior com Node.js com 30 perguntas práticas sobre event loop, streams, segurança de API, design de sistemas, escala, desempenho, testes e produção.


Perguntas Node.js para entrevista backend sênior

Entrevistas sênior de Node.js normalmente avaliam mais do que sintaxe. Espere perguntas sobre como você raciocina sobre event loop, backpressure, limites de API, sistemas distribuídos, observabilidade, segurança e decisões de produção. As melhores respostas conectam os detalhes internos do Node.js a decisões tomadas em serviços reais.

Use estas 30 perguntas para praticar explicações claras de nível sênior. Para cada tema, prepare um exemplo seu: uma decisão de escala, um problema de desempenho, um incidente de confiabilidade ou um tradeoff de design que você consiga explicar sem exagerar.


Conceitos Avançados de Node.js (10 Perguntas)

1. Explique o Loop de Eventos do Node.js em detalhes. Quais são as diferentes fases?

Resposta: O event loop permite que o Node.js execute E/S não bloqueante enquanto o JavaScript roda, por padrão, em uma única thread principal. O sistema operacional ou a libuv lidam com trabalho que fica aguardando, e depois os callbacks entram na fila para o JavaScript executar.

  • Timers: Executa callbacks de setTimeout() e setInterval(). Em versões modernas do Node.js, o trabalho na fase poll pode afetar o momento exato da execução.
  • Pending callbacks: Executa alguns callbacks de E/S de baixo nível adiados para a próxima iteração.
  • Idle, prepare: Fases internas da libuv.
  • Poll: Recupera novos eventos de E/S e executa callbacks relacionados. Se a fila estiver vazia, o Node.js pode esperar E/S ou avançar quando houver callbacks de setImmediate().
  • Check: Executa callbacks de setImmediate().
  • Close callbacks: Executa handlers de fechamento como socket.on('close', ...).

Uma resposta sênior também menciona as filas de microtasks: process.nextTick() roda antes das promises, e ambas rodam antes de o event loop continuar. Uso excessivo pode deixar a E/S sem vez.

Raridade: Muito Comum Dificuldade: Difícil


2. Qual é a diferença entre process.nextTick() e setImmediate()?

Resposta:

  • process.nextTick(): Não faz parte do Loop de Eventos. Ele é acionado imediatamente após a conclusão da operação atual, mas antes que o Loop de Eventos continue. Tem maior prioridade do que setImmediate(). O uso excessivo pode bloquear o Loop de Eventos (inanição).
  • setImmediate(): Faz parte da fase Check do Loop de Eventos. É executado após a fase Poll.

Raridade: Comum Dificuldade: Média


3. Como o Node.js lida com a concorrência se ele é single-threaded?

Resposta: O Node.js usa um modelo de E/S não bloqueante e orientado a eventos.

  • Thread Principal: Executa código JavaScript (motor V8).
  • Libuv: Uma biblioteca C que fornece o Loop de Eventos e um pool de threads (padrão de 4 threads).
  • Mecanismo: Quando uma operação assíncrona (como E/S de arquivo ou solicitação de rede) é iniciada, o Node.js a descarrega para a Libuv. A Libuv usa seu pool de threads (para E/S de arquivo, DNS) ou mecanismos assíncronos do kernel do sistema (para rede). Quando a operação é concluída, o callback é adicionado à fila do Loop de Eventos para ser executado pela thread principal.

Raridade: Comum Dificuldade: Média


4. Explique Streams no Node.js e seus tipos.

Resposta: Streams são objetos que permitem ler dados de uma fonte ou gravar dados em um destino em blocos contínuos. Eles são eficientes em termos de memória porque você não precisa carregar todos os dados na memória.

  • Tipos:
    1. Readable: Para leitura de dados (por exemplo, fs.createReadStream).
    2. Writable: Para gravação de dados (por exemplo, fs.createWriteStream).
    3. Duplex: Leitura e gravação (por exemplo, sockets TCP).
    4. Transform: Streams Duplex onde a saída é calculada com base na entrada (por exemplo, zlib.createGzip).

Raridade: Comum Dificuldade: Média


5. O que é Backpressure em Streams e como você o lida?

Resposta: Backpressure ocorre quando um stream readable produz dados mais rápido do que a parte writable consegue consumir. Se você ignorar isso, os buffers crescem, o garbage collector trabalha mais e o processo pode ficar sem memória.

  • Use stream.pipeline() ou pipeline de node:stream/promises: Conecta streams, propaga erros e limpa recursos corretamente.
  • Respeite .write(): Se retornar false, espere o evento drain antes de escrever mais.
  • Ajuste com cuidado: highWaterMark pode ajudar em workloads específicos, mas aumentar sem medir só desloca a pressão para a memória.
  • Para uploads: Faça streaming direto para object storage ou uma pipeline de processamento em vez de carregar arquivos inteiros na memória.

Raridade: Média Dificuldade: Difícil


6. Como o módulo cluster funciona?

Resposta: Como o Node.js é single-threaded, ele é executado em um único núcleo da CPU. O módulo cluster permite criar processos filhos (workers) que compartilham a mesma porta do servidor.

  • Processo Master: Gerencia os workers.
  • Processos Worker: Cada um executa uma instância do seu aplicativo.
  • Benefício: Permite utilizar todos os núcleos de CPU disponíveis, aumentando a taxa de transferência.

Raridade: Comum Dificuldade: Média


7. Worker Threads vs módulo Cluster: Quando usar qual?

Resposta:

  • Cluster: Cria processos separados. Cada um tem seu próprio espaço de memória e instância do V8. Melhor para escalar servidores HTTP (ligado a E/S).
  • Worker Threads: Cria threads dentro de um único processo. Eles compartilham memória (via SharedArrayBuffer). Melhor para tarefas intensivas em CPU (por exemplo, processamento de imagem, criptografia) para evitar bloquear o Loop de Eventos principal.

Raridade: Média Dificuldade: Difícil


8. Como você lida com exceções não capturadas e rejeições de promise não tratadas?

Resposta:

  • Exceção Não Capturada: Ouça process.on('uncaughtException', cb). Geralmente é melhor registrar o erro e reiniciar o processo (usando um gerenciador de processos como o PM2) porque o estado do aplicativo pode estar corrompido.
  • Rejeição Não Tratada: Ouça process.on('unhandledRejection', cb).
  • Melhor Prática: Sempre use blocos try/catch e .catch() em promises.

Raridade: Comum Dificuldade: Fácil


9. Qual é o papel do package-lock.json?

Resposta: Ele descreve a árvore exata que foi gerada, de modo que as instalações subsequentes sejam capazes de gerar árvores idênticas, independentemente das atualizações de dependência intermediárias. Ele garante que seu projeto funcione exatamente da mesma maneira em todas as máquinas (CI/CD, outros desenvolvedores).

Raridade: Comum Dificuldade: Fácil


10. Explique o conceito de Middleware no Express.js.

Resposta: Funções de middleware são funções que têm acesso ao objeto de solicitação (req), ao objeto de resposta (res) e à próxima função de middleware no ciclo de solicitação-resposta do aplicativo (next).

  • Tarefas: Executar código, modificar objetos req/res, finalizar o ciclo de solicitação-resposta, chamar o próximo middleware.
  • Ordem: Eles são executados sequencialmente na ordem em que são definidos.

Raridade: Comum Dificuldade: Fácil


Design e Arquitetura de Sistemas (10 Perguntas)

11. Como você projetaria um aplicativo de chat em tempo real?

Resposta:

  • Protocolo: WebSockets (usando socket.io ou ws) para comunicação full-duplex.
  • Backend: O Node.js é ideal devido à sua natureza orientada a eventos, lidando com muitas conexões simultâneas.
  • Escalonamento:
    • Redis Pub/Sub: Se você tiver várias instâncias de servidor, um usuário conectado ao Servidor A precisa enviar uma mensagem para um usuário no Servidor B. O Redis Pub/Sub atua como um message broker para transmitir mensagens entre os servidores.
  • Banco de Dados:
    • Mensagens: NoSQL (MongoDB/Cassandra) para alta taxa de transferência de gravação.
    • Usuários: Relacional (PostgreSQL) ou NoSQL.

Raridade: Muito Comum Dificuldade: Difícil


12. Microsserviços no Node.js: Padrões de comunicação.

Resposta:

  • Síncrono: HTTP/REST ou gRPC. Bom para solicitação/resposta simples.
  • Assíncrono: Filas de Mensagens (RabbitMQ, Kafka, SQS). Bom para desacoplar serviços e lidar com picos de carga.
  • Orientado a Eventos: Os serviços emitem eventos, outros ouvem.

Raridade: Comum Dificuldade: Média


13. Como você lida com Transações Distribuídas (Padrão Saga)?

Resposta: Em microsserviços, uma transação pode abranger vários serviços. ACID é difícil de garantir.

  • Padrão Saga: Uma sequência de transações locais. Cada transação local atualiza o banco de dados e publica um evento ou mensagem para acionar a próxima transação local na saga.
  • Compensação: Se uma transação local falhar, a saga executa uma série de transações compensatórias que desfazem as alterações feitas pelas transações locais precedentes.

Raridade: Média Dificuldade: Difícil


14. Explique o padrão Circuit Breaker.

Resposta: Ele impede que um aplicativo tente repetidamente executar uma operação que provavelmente falhará (por exemplo, chamar um microsserviço inativo).

  • Estados:
    • Fechado: As solicitações passam.
    • Aberto: As solicitações falham imediatamente (fast fail) sem chamar o serviço.
    • Semi-Aberto: Permite um número limitado de solicitações para verificar se o serviço se recuperou.

Raridade: Média Dificuldade: Média


15. Como você protege uma API Node.js?

Resposta: Uma resposta forte começa com modelagem de ameaças, não apenas uma lista de pacotes. Para uma API Node.js, cubra:

  • Autenticação e autorização: Valide identidade, aplique permissões no nível do objeto e não confie em IDs de usuário ou tenant enviados pelo cliente.
  • Validação de entrada: Valide tipo, formato, intervalo, content type e tamanho da requisição na borda com Zod, Joi ou similares.
  • Transporte e headers: Use HTTPS, cookies seguros quando aplicável, allowlists de CORS e headers com Helmet ou controles da plataforma.
  • Controles de abuso: Rate limits, timeouts, limites de tamanho do body e reverse proxy contra clientes lentos ou de alto volume.
  • Dependências e segredos: Trave dependências, monitore pacotes vulneráveis, mantenha segredos fora do código e rotacione credenciais comprometidas.
  • Observabilidade: Registre falhas relevantes para segurança sem vazar dados sensíveis.

Raridade: Comum Dificuldade: Média


16. O que é Serverless e como ele se encaixa com o Node.js?

Resposta: Serverless (por exemplo, AWS Lambda) permite que você execute código sem provisionar ou gerenciar servidores.

  • Encaixe com Node.js: O Node.js é excelente para serverless devido ao seu rápido tempo de inicialização (cold start) e natureza leve.
  • Casos de Uso: Pontos de extremidade de API, processamento de eventos (uploads S3), tarefas agendadas.

Raridade: Média Dificuldade: Média


17. Explique GraphQL vs REST. Quando usar GraphQL?

Resposta:

  • REST: Vários endpoints, over-fetching ou under-fetching de dados.
  • GraphQL: Endpoint único, o cliente pede exatamente o que precisa.
  • Use GraphQL: Quando você tem requisitos de dados complexos, vários clientes (web, mobile) precisando de diferentes formatos de dados ou para reduzir as viagens de ida e volta na rede.

Raridade: Comum Dificuldade: Média


18. Como você implementa o Caching no Node.js?

Resposta:

  • In-Memory: node-cache (bom para instância única, mas os dados são perdidos na reinicialização e não são compartilhados).
  • Distribuído: Redis (padrão da indústria).
  • Estratégias: Cache-Aside, Write-Through.
  • HTTP Caching: Use os cabeçalhos ETag, Cache-Control.

Raridade: Comum Dificuldade: Média


19. Pool de Conexões do Banco de Dados.

Resposta: Abrir uma nova conexão de banco de dados para cada solicitação é caro.

  • Pooling: Mantém um cache de conexões de banco de dados que podem ser reutilizadas.
  • Node.js: Bibliotecas como pg (PostgreSQL) ou mongoose lidam com o pooling automaticamente. Você precisa configurar o tamanho do pool com base na sua carga de trabalho e nos limites do DB.

Raridade: Média Dificuldade: Média


20. Como você lida com uploads de arquivos no Node.js?

Resposta:

  • Multipart/form-data: A codificação padrão para uploads de arquivos.
  • Bibliotecas: multer (middleware para Express), formidable, busboy.
  • Armazenamento: Não armazene arquivos no sistema de arquivos do servidor (statelessness). Faça upload para o armazenamento em nuvem como AWS S3. Transmita o arquivo diretamente para o S3 para evitar carregá-lo na memória.

Raridade: Comum Dificuldade: Média


Desempenho e Testes (10 Perguntas)

21. Como você depura um vazamento de memória no Node.js?

Resposta:

  • Sintomas: Aumento do uso de memória ao longo do tempo (RSS), eventual travamento.
  • Ferramentas:
    • Node.js Inspector: flag --inspect, conecte-se com o Chrome DevTools.
    • Heap Snapshots: Tire snapshots e compare-os para encontrar objetos que não estão sendo coletados pelo garbage collector.
    • process.memoryUsage(): Monitore programaticamente.

Raridade: Comum Dificuldade: Difícil


22. Profiling de Aplicações Node.js.

Resposta: O profiling ajuda a identificar gargalos de CPU.

  • Profiler Embutido: node --prof app.js. Gera um arquivo de log. Processe-o com node --prof-process isolate-0x...log.
  • Clinic.js: Um conjunto de ferramentas (clinic doctor, clinic flame, clinic bubbleprof) para diagnosticar problemas de desempenho.

Raridade: Média Dificuldade: Difícil


23. Explique a regra "Não Bloqueie o Loop de Eventos".

Resposta: Como existe apenas uma thread, se você executar uma operação síncrona de longa duração (por exemplo, cálculo pesado, leitura síncrona de arquivo, regex complexo), o Loop de Eventos para. Nenhuma outra solicitação pode ser processada.

  • Solução: Divida o cálculo (setImmediate), use Worker Threads ou descarregue para um microsserviço.

Raridade: Muito Comum Dificuldade: Fácil


24. Teste Unitário vs Teste de Integração no Node.js.

Resposta:

  • Teste Unitário: Testar funções/módulos individuais isoladamente. Mockar dependências. (Ferramentas: Jest, Mocha, Chai).
  • Teste de Integração: Testar como os módulos funcionam juntos (por exemplo, endpoint da API + Banco de Dados). (Ferramentas: Supertest).

Raridade: Comum Dificuldade: Fácil


25. O que é TDD (Test Driven Development)?

Resposta: Um processo de desenvolvimento onde você escreve o teste antes do código.

  1. Escreva um teste que falhe (Red).
  2. Escreva o código mínimo para passar no teste (Green).
  3. Refatore o código (Refactor).

Raridade: Média Dificuldade: Média


26. Como você lida com o logging em um aplicativo Node.js de produção?

Resposta: Logging em produção deve ser estruturado, pesquisável e seguro para ferramentas de observabilidade.

  • Use um logger: Pino, Winston ou o logger da plataforma em vez de console.log espalhados.
  • Estrutura: Emita JSON com request ID, identificadores seguros de usuário ou tenant, rota, status, latência e metadados do erro.
  • Níveis: Use error, warn, info e debug de forma consistente.
  • Redação: Nunca registre tokens, senhas, dados completos de pagamento ou conteúdo privado de usuários.
  • Correlação: Conecte logs com métricas e traces para depurar incidentes entre serviços.

Raridade: Comum Dificuldade: Fácil


27. Explique o Versionamento Semântico (SemVer).

Resposta: Formato: MAJOR.MINOR.PATCH (por exemplo, 1.2.3).

  • MAJOR: Mudanças incompatíveis na API.
  • MINOR: Funcionalidade compatível com versões anteriores.
  • PATCH: Correções de bugs compatíveis com versões anteriores.
  • ^ vs ~: ^1.2.3 atualiza para <2.0.0. ~1.2.3 atualiza para <1.3.0.

Raridade: Comum Dificuldade: Fácil


28. O que são Variáveis de Ambiente e como você as gerencia?

Resposta:

  • Propósito: Configuração que varia entre ambientes (Dev, Staging, Prod) como URLs de DB, chaves de API.
  • Uso: process.env.VARIABLE_NAME.
  • Gerenciamento: Arquivos .env (usando o pacote dotenv) para desenvolvimento local. Em produção, defina-os nas configurações do SO ou do contêiner/plataforma.

Raridade: Comum Dificuldade: Fácil


29. Como você implanta um aplicativo Node.js?

Resposta:

  • Gerenciador de Processos: PM2 (mantém o aplicativo ativo, lida com reinicializações, logs).
  • Reverse Proxy: Nginx (lida com SSL, arquivos estáticos, balanceamento de carga) -> Aplicativo Node.js.
  • Containerização: Docker (padrão).
  • Orquestração: Kubernetes.
  • CI/CD: GitHub Actions, Jenkins.

Raridade: Comum Dificuldade: Média


30. O que é Event Emitter?

Resposta: O módulo events é o núcleo da arquitetura orientada a eventos do Node.js.

  • Uso:
    const EventEmitter = require('events');
    const myEmitter = new EventEmitter();
    myEmitter.on('event', () => console.log('an event occurred!'));
    myEmitter.emit('event');
  • Muitos módulos principais o estendem: fs.ReadStream, net.Server, http.Server.

Raridade: Comum Dificuldade: Fácil

Newsletter subscription

Dicas de carreira semanais que realmente funcionam

Receba as últimas ideias diretamente na sua caixa de entrada

Crie um Currículo que Te Contrate 60% Mais Rápido

Em minutos, crie um currículo personalizado e compatível com ATS comprovado para conseguir 6 vezes mais entrevistas.

Crie um currículo melhor

Compartilhar esta publicação

Faça Seus 6 Segundos Contarem

Os recrutadores escaneiam currículos por uma média de apenas 6 a 7 segundos. Nossos modelos comprovados são projetados para capturar atenção instantaneamente e mantê-los lendo.