Entrevistas de Node.js giram em torno do event loop, padrões assíncronos, Express ou NestJS, e as consequências de um runtime de thread única. Abaixo estão as perguntas mais comuns com respostas modelo.
Cada pergunta vem com uma resposta modelo para você comparar com a sua.
1
Explique o event loop no Node.js. Quais são suas fases?
Resposta
O event loop processa repetidamente filas de operações concluídas em fases: timers para setTimeout e setInterval, pending callbacks, poll para I/O de entrada, check para setImmediate, e close callbacks. Entre cada fase o Node esvazia a fila de microtasks — primeiro process.nextTick, depois os callbacks de promises. É por isso que uma função síncrona longa bloqueia todo request no servidor: nada mais consegue rodar até ela retornar.
2
Qual é a diferença entre process.nextTick() e setImmediate()?
Resposta
process.nextTick enfileira um callback para rodar antes que o event loop siga para a próxima fase, antes das microtasks de promises. setImmediate agenda o callback para a fase check da próxima iteração. É por isso que nextTick sempre roda antes, e chamadas recursivas a nextTick podem esfomear o event loop por completo, por isso setImmediate é o padrão mais seguro para adiar trabalho.
3
O que é uma Promise? Explique Promise.all versus Promise.allSettled.
Resposta
Uma Promise representa um valor que estará disponível depois e está pending, fulfilled ou rejected. Promise.all resolve quando todo input resolve, mas rejeita imediatamente na primeira rejeição, descartando os outros resultados — exatamente quando você precisa de todos para continuar. Promise.allSettled sempre resolve com um status e valor para cada entrada, o que serve bem para operações independentes em que uma falha não deveria cancelar as demais.
4
Como você trata erros em async/await? O que acontece numa unhandled rejection?
Resposta
Você envolve as chamadas com await em try/catch, ou anexa .catch na promise retornada. No Express, um erro lançado dentro de um handler async não é capturado pelo framework a menos que você o repasse para next(), então a maioria das equipes usa um wrapper ou express-async-errors. Uma unhandled rejection encerra o processo por padrão no Node moderno, o que é intencional — o processo está num estado desconhecido e deveria reiniciar.
5
O que são streams e quando você os usa em vez de ler um arquivo inteiro?
Resposta
Streams processam dados em chunks, então o uso de memória permanece constante não importa o tamanho do payload, e o primeiro byte pode ser enviado antes de ler o último. Ler um arquivo de dois gigabytes num Buffer esgota a memória e atrasa a resposta; fazer pipe transmite direto para o cliente. Streams também se compõem via pipe ou pipeline, deixando você encadear descompressão, transformação e saída com o backpressure gerenciado para você.
6
O que é middleware no Express? Como o next() funciona?
Resposta
Middleware é uma função que recebe request, response e next, executada na ordem de registro para formar um pipeline. Chamar next() passa o controle para o próximo middleware; não chamá-lo e não enviar uma resposta deixa o request pendurado. Passar um argumento para next() pula direto para o middleware de tratamento de erros, reconhecido por ter quatro parâmetros.
7
Como o Node lida com tarefas intensivas em CPU? O que são worker threads?
Resposta
Como o JavaScript roda numa única thread, um cálculo pesado em CPU bloqueia todo request pendente. Worker threads rodam JavaScript em threads paralelas dentro do mesmo processo, se comunicando por passagem de mensagens e shared array buffers, o que serve bem para hashing, processamento de imagens ou parsing. As alternativas são delegar para um serviço separado ou uma fila de jobs — clustering só adiciona processos e não acelera um único request.
8
O que é um JWT? Onde você o guarda e quais são os riscos?
Resposta
Um JWT é um token assinado que carrega claims, então o servidor consegue autenticar um request sem uma busca de sessão. Guardá-lo no localStorage o expõe a XSS; guardá-lo num cookie httpOnly, Secure, SameSite protege contra XSS mas exige defesa contra CSRF. O trade-off mais profundo é a revogação: um token stateless continua válido até expirar, então sistemas sensíveis usam access tokens de vida curta com refresh tokens e uma denylist do lado do servidor.
9
Qual é a diferença entre require e import? O que são CommonJS e ESM?
Resposta
CommonJS require é síncrono, resolvido em runtime, e pode ser chamado condicionalmente dentro de uma função. ESM import é estático, hoisted, e é analisado antes da execução, o que habilita tree shaking e top-level await. Um pacote declara seu formato com "type": "module" ou as extensões .mjs e .cjs; ESM consegue importar CommonJS, mas o contrário precisa de um import() dinâmico porque require não consegue carregar um grafo de módulos assíncrono.
10
Como você implementa um graceful shutdown?
Resposta
Ao receber SIGTERM você para de aceitar novas conexões com server.close(), deixa os requests em andamento terminarem, depois fecha os pools de banco de dados, consumidores de mensagens e timers antes de sair. Um timeout força a saída se algo travar, então o container nunca fica preso. Sem isso, um deploy mata requests no meio do caminho e pode deixar transações ou mensagens de fila num estado inconsistente.