декабря 21, 2025
10 мин. чтения

Вопросы по Node.js для Senior Backend собеседования

interview
career-advice
job-search
Вопросы по Node.js для Senior Backend собеседования
Milad Bonakdar

Milad Bonakdar

Автор

Подготовьтесь к Senior Backend собеседованиям по Node.js: 30 практических вопросов про event loop, streams, безопасность API, system design, масштабирование, производительность, тестирование и production.


Вопросы по Node.js для Senior Backend собеседования

Senior-собеседование по Node.js обычно проверяет не только синтаксис. Ожидайте вопросы о том, как вы рассуждаете про event loop, backpressure, границы API, распределенные системы, observability, безопасность и production-компромиссы. Сильные ответы связывают внутреннее устройство Node.js с решениями, которые вы принимали в реальных сервисах.

Используйте эти 30 вопросов, чтобы отработать короткие ответы senior-уровня. Для каждой темы подготовьте пример из собственного опыта: решение по масштабированию, проблему производительности, инцидент надежности или архитектурный компромисс, который вы можете объяснить без преувеличений.


Продвинутые концепции Node.js (10 вопросов)

1. Подробно объясните Node.js Event Loop. Какие существуют фазы?

Ответ: Event loop позволяет Node.js выполнять неблокирующий ввод-вывод, пока JavaScript по умолчанию работает в одном основном потоке. Ожидающую или тяжелую работу берет на себя операционная система или libuv, а затем callbacks попадают в очередь выполнения JavaScript.

  • Timers: Выполняет callbacks из setTimeout() и setInterval(). В современных версиях Node.js работа в фазе poll может влиять на точный момент запуска таймеров.
  • Pending callbacks: Выполняет некоторые низкоуровневые I/O callbacks, отложенные до следующей итерации.
  • Idle, prepare: Внутренние фазы libuv.
  • Poll: Получает новые I/O события и выполняет связанные callbacks. Если очередь пуста, Node.js может ждать I/O или перейти дальше, когда есть callbacks setImmediate().
  • Check: Выполняет callbacks setImmediate().
  • Close callbacks: Выполняет обработчики закрытия, например socket.on('close', ...).

Senior-ответ также должен упомянуть microtask queues: process.nextTick() выполняется раньше promise microtasks, и оба типа выполняются до продолжения event loop. Чрезмерное использование может лишить I/O времени на выполнение.

Редкость: Очень часто Сложность: Сложно


2. В чем разница между process.nextTick() и setImmediate()?

Ответ:

  • process.nextTick(): Это не часть Event Loop. Он срабатывает сразу после завершения текущей операции, но до продолжения Event Loop. Он имеет более высокий приоритет, чем setImmediate(). Чрезмерное использование может заблокировать Event Loop (голодание).
  • setImmediate(): Это часть фазы Check Event Loop. Он запускается после фазы Poll.

Редкость: Часто Сложность: Средне


3. Как Node.js обрабатывает параллелизм, если он однопоточный?

Ответ: Node.js использует управляемую событиями, неблокирующую модель ввода-вывода.

  • Основной поток: Выполняет код JavaScript (движок V8).
  • Libuv: Библиотека C, которая предоставляет Event Loop и пул потоков (по умолчанию 4 потока).
  • Механизм: Когда инициируется асинхронная операция (например, файловый ввод-вывод или сетевой запрос), Node.js перекладывает ее на Libuv. Libuv использует свой пул потоков (для файлового ввода-вывода, DNS) или асинхронные механизмы системного ядра (для сети). Когда операция завершается, обратный вызов помещается в очередь Event Loop для выполнения основным потоком.

Редкость: Часто Сложность: Средне


4. Объясните Streams в Node.js и их типы.

Ответ: Streams - это объекты, которые позволяют читать данные из источника или записывать данные в приемник непрерывными кусками. Они эффективны с точки зрения памяти, потому что вам не нужно загружать все данные в память.

  • Типы:
    1. Readable: Для чтения данных (например, fs.createReadStream).
    2. Writable: Для записи данных (например, fs.createWriteStream).
    3. Duplex: И для чтения, и для записи (например, TCP-сокеты).
    4. Transform: Duplex-потоки, где вывод вычисляется на основе ввода (например, zlib.createGzip).

Редкость: Часто Сложность: Средне


5. Что такое Backpressure в Streams и как с этим бороться?

Ответ: Backpressure возникает, когда readable stream производит данные быстрее, чем writable-сторона может их обработать. Если это игнорировать, растут буферы, усиливается нагрузка на garbage collector, и процесс может исчерпать память.

  • Используйте stream.pipeline() или pipeline из node:stream/promises: Это соединяет streams, передает ошибки и корректно очищает ресурсы.
  • Уважайте .write(): Если метод возвращает false, дождитесь drain, прежде чем писать дальше.
  • Настраивайте осторожно: highWaterMark может помочь в конкретных нагрузках, но без измерений он просто переносит давление в память.
  • Для uploads: Передавайте файл stream-ом напрямую в object storage или pipeline обработки, не буферизуя весь файл в памяти.

Редкость: Средне Сложность: Сложно


6. Как работает модуль cluster?

Ответ: Поскольку Node.js является однопоточным, он работает на одном ядре ЦП. Модуль cluster позволяет создавать дочерние процессы (рабочие), которые совместно используют один и тот же порт сервера.

  • Основной процесс: Управляет рабочими.
  • Рабочие процессы: Каждый запускает экземпляр вашего приложения.
  • Преимущество: Позволяет использовать все доступные ядра ЦП, увеличивая пропускную способность.

Редкость: Часто Сложность: Средне


7. Worker Threads vs модуль Cluster: Когда что использовать?

Ответ:

  • Cluster: Создает отдельные процессы. Каждый имеет свое собственное адресное пространство и экземпляр V8. Лучше всего подходит для масштабирования HTTP-серверов (связанных с вводом-выводом).
  • Worker Threads: Создает потоки внутри одного процесса. Они совместно используют память (через SharedArrayBuffer). Лучше всего подходит для задач, интенсивно использующих ЦП (например, обработка изображений, криптография), чтобы избежать блокировки основного Event Loop.

Редкость: Средне Сложность: Сложно


8. Как обрабатывать необработанные исключения и необработанные отклонения промисов?

Ответ:

  • Uncaught Exception: Слушайте process.on('uncaughtException', cb). Обычно лучше всего регистрировать ошибку и перезапускать процесс (используя менеджер процессов, такой как PM2), потому что состояние приложения может быть повреждено.
  • Unhandled Rejection: Слушайте process.on('unhandledRejection', cb).
  • Лучшая практика: Всегда используйте блоки try/catch и .catch() для промисов.

Редкость: Часто Сложность: Легко


9. Какова роль package-lock.json?

Ответ: Он описывает точное дерево, которое было сгенерировано, так что последующие установки могут генерировать идентичные деревья, независимо от промежуточных обновлений зависимостей. Это гарантирует, что ваш проект работает одинаково на каждой машине (CI/CD, другие разработчики).

Редкость: Часто Сложность: Легко


10. Объясните концепцию Middleware в Express.js.

Ответ: Middleware-функции - это функции, которые имеют доступ к объекту запроса (req), объекту ответа (res) и следующей middleware-функции в цикле запрос-ответ приложения (next).

  • Задачи: Выполнение кода, изменение объектов req/res, завершение цикла запрос-ответ, вызов следующей middleware.
  • Порядок: Они выполняются последовательно в том порядке, в котором они определены.

Редкость: Часто Сложность: Легко


Системный дизайн и архитектура (10 вопросов)

11. Как бы вы спроектировали приложение для чата в реальном времени?

Ответ:

  • Протокол: WebSockets (с использованием socket.io или ws) для полнодуплексной связи.
  • Серверная часть: Node.js идеально подходит благодаря своей управляемой событиями природе, обрабатывающей множество одновременных соединений.
  • Масштабирование:
    • Redis Pub/Sub: Если у вас несколько экземпляров сервера, пользователю, подключенному к Серверу A, необходимо отправить сообщение пользователю на Сервере B. Redis Pub/Sub действует как брокер сообщений для трансляции сообщений между серверами.
  • База данных:
    • Сообщения: NoSQL (MongoDB/Cassandra) для высокой пропускной способности записи.
    • Пользователи: Реляционная (PostgreSQL) или NoSQL.

Редкость: Очень часто Сложность: Сложно


12. Микросервисы в Node.js: шаблоны коммуникации.

Ответ:

  • Синхронный: HTTP/REST или gRPC. Хорошо подходит для простых запросов/ответов.
  • Асинхронный: Очереди сообщений (RabbitMQ, Kafka, SQS). Хорошо подходит для разделения сервисов и обработки скачков нагрузки.
  • Управляемый событиями: Сервисы генерируют события, другие их слушают.

Редкость: Часто Сложность: Средне


13. Как обрабатывать распределенные транзакции (паттерн Saga)?

Ответ: В микросервисах транзакция может охватывать несколько сервисов. ACID трудно гарантировать.

  • Паттерн Saga: Последовательность локальных транзакций. Каждая локальная транзакция обновляет базу данных и публикует событие или сообщение для запуска следующей локальной транзакции в саге.
  • Компенсация: Если локальная транзакция завершается неудачно, сага выполняет серию компенсирующих транзакций, которые отменяют изменения, внесенные предыдущими локальными транзакциями.

Редкость: Средне Сложность: Сложно


14. Объясните паттерн Circuit Breaker.

Ответ: Он предотвращает многократные попытки приложения выполнить операцию, которая, вероятно, завершится неудачей (например, вызов неработающего микросервиса).

  • Состояния:
    • Closed: Запросы проходят.
    • Open: Запросы немедленно завершаются неудачей (fast fail) без вызова сервиса.
    • Half-Open: Разрешает ограниченное количество запросов, чтобы проверить, восстановился ли сервис.

Редкость: Средне Сложность: Средне


15. Как защитить Node.js API?

Ответ: Сильный ответ начинается с threat modeling, а не со списка пакетов. Для Node.js API стоит покрыть:

  • Authentication и authorization: Проверяйте личность, применяйте права на уровне объекта и не доверяйте user/tenant ID, присланным клиентом.
  • Input validation: На границе проверяйте тип, формат, диапазон, content type и размер запроса с помощью Zod, Joi или аналогов.
  • Transport и headers: Используйте HTTPS, secure cookies где нужно, CORS allowlists и заголовки через Helmet или средства платформы.
  • Abuse controls: Rate limits, timeouts, body-size limits и reverse proxy против медленных или массовых клиентов.
  • Dependencies и secrets: Фиксируйте зависимости, отслеживайте уязвимые пакеты, не храните secrets в коде и ротируйте скомпрометированные credentials.
  • Observability: Логируйте важные для безопасности сбои, не раскрывая чувствительные данные.

Редкость: Часто Сложность: Средне


16. Что такое Serverless и как это соотносится с Node.js?

Ответ: Serverless (например, AWS Lambda) позволяет запускать код без выделения или управления серверами.

  • Соответствие Node.js: Node.js отлично подходит для serverless благодаря быстрому времени запуска (холодный старт) и легкому характеру.
  • Сценарии использования: API-endpoints, обработка событий (загрузка S3), запланированные задачи.

Редкость: Средне Сложность: Средне


17. Объясните GraphQL vs REST. Когда использовать GraphQL?

Ответ:

  • REST: Несколько endpoints, переизвлечение или недоизвлечение данных.
  • GraphQL: Один endpoint, клиент запрашивает именно то, что ему нужно.
  • Используйте GraphQL: Когда у вас сложные требования к данным, несколько клиентов (веб, мобильные), которым нужны разные формы данных, или для сокращения количества сетевых обходов.

Редкость: Часто Сложность: Средне


18. Как реализовать кэширование в Node.js?

Ответ:

  • In-Memory: node-cache (хорошо подходит для одного экземпляра, но данные теряются при перезапуске и не передаются).
  • Distributed: Redis (отраслевой стандарт).
  • Стратегии: Cache-Aside, Write-Through.
  • HTTP Caching: Используйте ETag, заголовки Cache-Control.

Редкость: Часто Сложность: Средне


19. Пул соединений с базой данных.

Ответ: Открытие нового соединения с базой данных для каждого запроса является дорогостоящим.

  • Pooling: Поддерживает кэш соединений с базой данных, которые можно использовать повторно.
  • Node.js: Библиотеки, такие как pg (PostgreSQL) или mongoose, автоматически обрабатывают пул. Вам необходимо настроить размер пула в зависимости от вашей рабочей нагрузки и лимитов DB.

Редкость: Средне Сложность: Средне


20. Как обрабатывать загрузку файлов в Node.js?

Ответ:

  • Multipart/form-data: Стандартная кодировка для загрузки файлов.
  • Библиотеки: multer (middleware для Express), formidable, busboy.
  • Хранилище: Не храните файлы в файловой системе сервера (statelessness). Загрузите в облачное хранилище, такое как AWS S3. Передайте файл непосредственно в S3, чтобы избежать загрузки его в память.

Редкость: Часто Сложность: Средне


Производительность и тестирование (10 вопросов)

21. Как отладить утечку памяти в Node.js?

Ответ:

  • Симптомы: Увеличение использования памяти с течением времени (RSS), возможный сбой.
  • Инструменты:
    • Node.js Inspector: Флаг --inspect, подключитесь с помощью Chrome DevTools.
    • Heap Snapshots: Делайте снимки и сравнивайте их, чтобы найти объекты, которые не удаляются сборщиком мусора.
    • process.memoryUsage(): Мониторинг программно.

Редкость: Часто Сложность: Сложно


22. Профилирование Node.js приложений.

Ответ: Профилирование помогает выявить узкие места ЦП.

  • Встроенный Profiler: node --prof app.js. Генерирует файл журнала. Обработайте его с помощью node --prof-process isolate-0x...log.
  • Clinic.js: Набор инструментов (clinic doctor, clinic flame, clinic bubbleprof) для диагностики проблем с производительностью.

Редкость: Средне Сложность: Сложно


23. Объясните правило "Don't Block the Event Loop".

Ответ: Поскольку существует только один поток, если вы выполняете длительную синхронную операцию (например, сложные вычисления, синхронное чтение файла, сложный regex), Event Loop останавливается. Никакие другие запросы не могут быть обработаны.

  • Решение: Разделите вычисления (setImmediate), используйте Worker Threads или переложите на микросервис.

Редкость: Очень часто Сложность: Легко


24. Unit Testing vs Integration Testing в Node.js.

Ответ:

  • Unit Testing: Тестирование отдельных функций/модулей в изоляции. Mock-зависимости. (Инструменты: Jest, Mocha, Chai).
  • Integration Testing: Тестирование того, как модули работают вместе (например, API-endpoint + база данных). (Инструменты: Supertest).

Редкость: Часто Сложность: Легко


25. Что такое TDD (Test Driven Development)?

Ответ: Процесс разработки, при котором вы пишете тест до кода.

  1. Напишите неудачный тест (Red).
  2. Напишите минимальный код для прохождения теста (Green).
  3. Рефакторинг кода (Refactor).

Редкость: Средне Сложность: Средне


26. Как обрабатывать логирование в production Node.js приложении?

Ответ: Production-логирование должно быть структурированным, удобным для поиска и безопасным для observability-инструментов.

  • Используйте logger: Pino, Winston или logger платформы вместо разрозненных console.log.
  • Структура: Пишите JSON с request ID, безопасными user/tenant идентификаторами, route, status, latency и metadata ошибки.
  • Levels: Последовательно используйте error, warn, info и debug.
  • Redaction: Не логируйте tokens, passwords, полные платежные данные или приватный пользовательский контент.
  • Correlation: Связывайте logs с metrics и traces, чтобы разбирать инциденты между сервисами.

Редкость: Часто Сложность: Легко


27. Объясните Semantic Versioning (SemVer).

Ответ: Формат: MAJOR.MINOR.PATCH (например, 1.2.3).

  • MAJOR: Несовместимые изменения API.
  • MINOR: Обратно совместимая функциональность.
  • PATCH: Обратно совместимые исправления ошибок.
  • ^ vs ~: ^1.2.3 обновляется до <2.0.0. ~1.2.3 обновляется до <1.3.0.

Редкость: Часто Сложность: Легко


28. Что такое Environment Variables и как ими управлять?

Ответ:

  • Цель: Конфигурация, которая варьируется между средами (Dev, Staging, Prod), такими как URL-адреса DB, ключи API.
  • Использование: process.env.VARIABLE_NAME.
  • Управление: Файлы .env (с использованием пакета dotenv) для локальной разработки. В production установите их в настройках ОС или контейнера/платформы.

Редкость: Часто Сложность: Легко


29. Как развернуть Node.js приложение?

Ответ:

  • Process Manager: PM2 (поддерживает работу приложения, обрабатывает перезапуски, логи).
  • Reverse Proxy: Nginx (обрабатывает SSL, статические файлы, балансировку нагрузки) -> Node.js App.
  • Containerization: Docker (стандарт).
  • Orchestration: Kubernetes.
  • CI/CD: GitHub Actions, Jenkins.

Редкость: Часто Сложность: Средне


30. Что такое Event Emitter?

Ответ: Модуль events является ядром управляемой событиями архитектуры Node.js.

  • Использование:
    const EventEmitter = require('events');
    const myEmitter = new EventEmitter();
    myEmitter.on('event', () => console.log('an event occurred!'));
    myEmitter.emit('event');
  • Многие основные модули расширяют его: fs.ReadStream, net.Server, http.Server.

Редкость: Часто Сложность: Легко

Newsletter subscription

Еженедельные советы по карьере, которые действительно работают

Получайте последние идеи прямо на вашу почту

Создайте резюме, которое поможет вам устроиться на 60% быстрее

За несколько минут создайте персонализированное резюме, совместимое с ATS, которое доказано увеличивает количество собеседований в 6 раз.

Создать лучшее резюме

Поделиться этим постом

Устройтесь на Работу на 50% Быстрее

Соискатели, использующие профессиональные резюме с улучшением ИИ, находят работу в среднем за 5 недель по сравнению со стандартными 10. Перестаньте ждать и начните проходить собеседования.