Node.js 20 в статусе EOL: как обновить API, SSR и фоновые обработчики без остановки заказов

На сервере всё ещё работает Node.js 20, поэтому кажется, что обновление можно отложить. Но ветка уже находится в статусе EOL: штатных обновлений безопасности для неё больше нет.

Найдите все процессы Node.js, включая фоновые задания и сборку. Выберите поддерживаемую ветку по совместимости приложения, а не только по номеру версии. На тесте проведите заказ через API, SSR, очередь и вебхук; перед рабочим переключением подготовьте откат и наблюдение за ошибками.

Параллельное обновление Node.js для API, SSR и фоновых обработчиков с тестами и откатом
Содержание 24 разделов

Что делать бизнесу, у которого JS-сервисы всё ещё работают на 20-й ветке

Статья адресована владельцам JavaScript-сервисов, интернет-магазинов, API и внутренних приложений, которые используют Node.js 20 в production и должны решить, когда и как переходить на поддерживаемую версию.

По официальному списку Node.js, ветка 20 (Iron) достигла EOL 24 марта 2026 года, а не 30 апреля. Приложение от этого не выключается, но штатная поддержка и исправления безопасности для ветки закончились. План обновления должен охватывать API, SSR, фоновые обработчики, зависимости и сценарий отката.

Почему «работает же» — не аргумент

Если сервис на Node.js 20 продолжает принимать заказы, это не доказательство его безопасности. Проверьте, где запущен этот runtime, какие пакеты и нативные модули от него зависят, и сравните критичные операции на поддерживаемой версии. Особенно внимательно тестируйте очереди, повторы и вебхуки: ошибка в них не всегда видна на главной странице.

Что именно означает статус EOL

«Last updated» ≠ дата окончания поддержки

На странице релизов nodejs.org у каждой ветки есть колонка «Last updated» — это дата последнего фактического патч-релиза (для 20-й ветки — 24 марта 2026, версия 20.20.2) [1]. Это не то же самое, что дата окончания планового жизненного цикла. Плановая дата EOL для чётных LTS-веток фиксируется заранее и почти всегда приходится на 30 апреля соответствующего года — независимо от того, когда вышел последний патч [5][8]. Для Node.js 20 это 30 апреля 2026 года — дата, подтверждённая как на самой странице EOL nodejs.org, так и в независимых обзорах жизненного цикла [2][4][8].

Путаница здесь встречается системно: команды смотрят на «Last updated», видят недавнюю дату и делают вывод, что версия ещё «свежая», хотя статус уже — EOL. Важно помнить и обратное: сам факт истечения поддержки не означает, что приложение немедленно остановится или сломается — риск накапливается постепенно, а не проявляется одномоментно.

Что произойдёт, если ничего не делать

Ничего резкого. Ни один процесс не остановится сам. Но начнут накапливаться параллельные риски:

  • Отсутствие патчей безопасности. Новые уязвимости в V8, npm, OpenSSL или ядре Node для 20-й ветки закрываться не будут [2].
  • Разрыв с экосистемой. Библиотеки и SDK постепенно поднимают минимальную требуемую версию Node в поле engines. Например, Salesforce CLI объявил переход на требование Node ≥ 22, ссылаясь напрямую на то, что 18-я и 20-я ветки достигли EOL [7].
  • Проблемы с комплаенсом. Многие отраслевые аудиты и внутренние политики безопасности прямо запрещают использование неподдерживаемых рантаймов [2].
  • Поломка сборки при обновлении базовых Docker-образов. Официальные образы node:20 со временем перестают обновляться.

Три коммерческих партнёра OpenJS Foundation — HeroDevs, NodeSource и TuxCare — предлагают платный бэкпорт патчей безопасности для EOL-версий Node.js как временную меру для тех, кто пока не может обновиться [2][4]. Это явно позиционируется как временное решение, а не альтернатива апгрейду [2].

Как найти все места, где реально работает Node.js

Где живёт Node.js: API → SSR → Фоновые задачи
Где живёт Node.js: API, SSR, Фоновые задачи.

Production-серверы и менеджеры процессов

  • Проверить фактическую версию на каждом сервере: node -v или process.version внутри приложения [8], а не то, что записано в документации проекта.
  • Посмотреть конфигурацию менеджеров процессов (PM2, systemd unit-файлы, supervisord) — там часто зашит абсолютный путь к бинарнику конкретной версии Node.
  • Проверить serverless-функции отдельно: у облачных провайдеров рантаймы Node деактивируются поэтапно (например, у AWS Lambda процесс отключения версии идёт в три фазы — сначала прекращаются патчи безопасности, затем блокируется создание новых функций, затем блокируется обновление существующих) [3]. Дедлайны в облаке могут не совпадать с датой EOL самого Node.js и наступать раньше.

Dockerfile и базовые образы

  • Найти все FROM node:... во всех Dockerfile’ах, включая базовые образы для CI-раннеров и локальной разработки.
  • Проверить теги на плавающие версии (node:20, node:lts) — они могли незаметно «уехать» на другую минорную версию внутри 20-й ветки, но мажорная ветка всё равно останется EOL.
  • Проверить .dockerignore: если в образ копируются локально собранные node_modules с уже скомпилированными нативными модулями, при смене версии Node внутри контейнера они могут не совпасть по ABI с рантаймом контейнера — ошибка проявится не на этапе сборки, а только при первом обращении к модулю в проде [14].

CI/CD и сборочные пайплайны

  • Проверить файлы .nvmrc, .node-version, поле engines в package.json, а также явное указание версии Node в конфигурации CI (GitHub Actions setup-node, GitLab CI образы, Jenkins-агенты).
  • Частая ситуация: production обновили, а CI продолжает собирать и тестировать сборку на старой версии — тесты «зелёные», но не на той версии, что реально в проде.

SSR-фреймворки и edge-рантаймы

  • Отдельно проверить окружение серверного рендеринга: Next.js, Nuxt, Remix и подобные фреймворки нередко запускаются в отдельном контейнере или на отдельной платформе со своей версией Node, которая может отличаться от версии основного API.
  • Проверить, поддерживает ли используемая мажорная версия фреймворка целевую версию Node.

Что проверить перед выбором целевой версии

Зависимости, lock-файлы, поле engines

Нужно пройтись по package-lock.json/yarn.lock/pnpm-lock.yaml и проверить:

  • какие пакеты в engines явно ограничивают диапазон поддерживаемых версий Node;
  • какие мажорные версии критичных зависимостей (ORM, HTTP-клиент, очереди, драйвер БД) требуются для совместимости с целевой веткой;
  • нет ли пакетов, которые официально прекратили поддержку и требуют замены параллельно с апгрейдом Node.

Нативные расширения и ABI

Каждая мажорная версия Node меняет ABI (NODE_MODULE_VERSION), и любой пакет с нативным кодом — .node-бинарником, собранным через node-gyp, — должен быть пересобран или переустановлен под новую версию, иначе процесс упадёт при попытке его загрузить [9][11].

Если зависимости используют Node-API (N-API), а не устаревшие V8-заголовки напрямую, гарантируется ABI-стабильность между мажорными версиями [9][13]. Но на практике многие пакеты смешивают N-API с прямыми обращениями к V8 или NAN — такие места являются самыми частыми источниками поломок при мажорном апгрейде [10]. Практическая проверка:

  1. Полная чистая переустановка (rm -rf node_modules && npm ci) на целевой версии Node.
  2. Явный npm rebuild для пакетов с нативным кодом.
  3. Прогон полного тестового набора именно на целевой версии.

Если критичная зависимость с нативным кодом ещё не публикует сборки под самую свежую LTS, разумный компромисс — временно остановиться на предыдущей поддерживаемой ветке (сейчас это Node 22, Maintenance LTS), а не оставаться на уже снятой с поддержки версии [12].

Поддержка фреймворков и облачных платформ

Отдельно стоит свериться с матрицей поддерживаемых версий Node у используемого хостинга, PaaS-платформы, менеджера очередей и мониторинга.

Как выбрать поддерживаемую ветку

Правило Node.js: только чётные версии получают статус LTS, каждая живёт около 30 месяцев (12 месяцев Active LTS + 18 месяцев Maintenance), переход в Maintenance-фазу обычно происходит в октябре, а окончание поддержки — в апреле [5][8]. На момент выхода этой статьи:

План обновления: Найти версии → Проверить зависимости → Выбрать поддержку
План обновления: Найти версии, Проверить зависимости, Выбрать поддержку.
  • Node.js 22 — Maintenance LTS, поддержка до 30 апреля 2027 года;
  • Node.js 24 — Active LTS, поддержка до 30 апреля 2028 года.

Официальная позиция мейнтейнеров проекта — переходить сразу на Node.js 24, если это возможно, а не на 22: 22-я ветка уже находится в фазе сопровождения и получит статус EOL на год раньше [6]. Единственная разумная причина выбрать 22 вместо 24 — если критичная зависимость (чаще всего с нативным кодом) ещё не поддерживает 24-ю ветку [12]. Ориентироваться нужно не на «самую новую версию» саму по себе, а на пересечение: какая версия одновременно является LTS, поддерживается всеми критичными зависимостями и совместима с используемыми SSR-фреймворками и облачной платформой.

Российская специфика: ФСТЭК, БДУ и управление уязвимостями

Сам по себе рантайм Node.js — открытое ПО с международной разработкой, и вопрос о включении в реестр отечественного ПО к нему не применяется. Российская специфика лежит в другой плоскости — в требованиях к управлению уязвимостями.

Если компания — субъект критической информационной инфраструктуры (187-ФЗ) или проходит аудит на соответствие требованиям ФСТЭК России, снятый с поддержки рантайм рассматривается как открытая, неустранимая уязвимость. Банк данных угроз безопасности информации (БДУ) ФСТЭК ведёт публичный реестр уязвимостей программного и программно-аппаратного обеспечения, сопоставленный с международными идентификаторами CVE [15]. Приказ ФСТЭК №235 закрепляет требования к защите объектов КИИ, а бесплатный сканер ScanOVAL, работающий на OVAL-контенте с портала bdu.fstec.ru, выявляет использование программных компонентов с известными уязвимостями на конкретном хосте [16]. Коммерческие сканеры вроде MaxPatrol VM выполняют ту же задачу в масштабе инфраструктуры и рассчитывают SLA на устранение по каждой найденной уязвимости [17].

Фоновые обработчики: очереди, вебхуки, повторы после сбоя

Апгрейд версии Node чаще всего тестируют на HTTP-слое и забывают про фоновые процессы — а именно там чаще всего теряются данные при деплое [20].

Node.js по умолчанию завершается по SIGTERM немедленно, без дренажа: активные HTTP-запросы обрываются, открытые транзакции БД откатываются, а обработчики очередей теряют состояние выполняемой задачи [18]. Для очередей на базе BullMQ, например, у воркера есть метод, который прекращает забор новых задач и ждёт завершения текущей — но только в пределах заданного тайм-аута; просроченные задачи уходят в очередь повторов согласно настроенной политике retry [18][21].

Что стоит проверить отдельно от основного API до переключения на новую версию Node:

  • Обработка вебхуков. Идемпотентность обработчика (повторная доставка того же вебхука не должна создавать дубликат заказа), корректная проверка подписи запроса, поведение при таймауте на стороне партнёра.
  • Фоновые очереди. Поведение при штатном перезапуске воркера: завершаются ли активные задачи, не теряются ли задачи, стоящие в очереди на момент остановки.
  • Повторы после сбоя. Политика retry (число попыток, экспоненциальная задержка, дедупликация) должна быть протестирована именно на целевой версии Node — как отдельный сценарий с реальным поднятием и штатной остановкой процесса.

Как сравнить SSR и критичные API на тестовом трафике

Тест критичного пути: Новый заказ → Платёжный ответ → Нет дублей
Тест критичного пути: Новый заказ, Платёжный ответ, Нет дублей.
  1. Теневой (shadow) трафик. Копия части реальных запросов направляется одновременно на старую и новую версию, ответы сравниваются, но пользователю возвращается только ответ от текущей продакшн-версии.
  2. Canary-развёртывание. Небольшая доля реального трафика (обычно 1–10%) обслуживается новой версией, при этом отслеживаются метрики ошибок, задержки и потребления памяти в динамике — некоторые проблемы проявляются не сразу, а спустя 10–15 минут работы [19].
  3. Сравнение SSR отдельно от API. Для серверного рендеринга важно сверять не только код ответа, но и содержимое отрендеренной страницы — расхождения проявляются именно в HTML-выводе, а не в статус-кодах.
  4. Health-check, который не врёт. Эндпоинт проверки готовности должен реально проверять соединение с базой данных и внешними зависимостями, а не просто отвечать 200 OK [19].

Поэтапное переключение и откат

  • Rolling-обновление. Инстансы заменяются по одному или небольшими группами, каждый корректно дренируется по SIGTERM перед остановкой [19].
  • Blue-green. Полный параллельный набор инстансов на новой версии разворачивается рядом со старым, трафик переключается разом после проверки, откат — мгновенное переключение обратно.
  • Canary. Постепенное увеличение доли трафика на новую версию с постоянным мониторингом метрик; при отклонениях — автоматический или ручной откат.

Общее условие для любой из стратегий — заранее готовый и проверенный путь отката: старая версия должна оставаться развёрнутой или мгновенно разворачиваемой, пока новая версия не отработала в проде достаточное время без инцидентов [19].

Переключение без сюрпризов: Пилотный трафик → Мониторинг ошибок → План отката
Переключение без сюрпризов: Пилотный трафик, Мониторинг ошибок, План отката.

Практический результат: план обновления

Ниже — сводный чек-лист, который можно использовать как рабочий план миграции.

Зависимости и окружение для проверки:

  • версия Node в .nvmrc / .node-version / engines в package.json;
  • версия Node во всех Dockerfile (production, CI-раннеры, локальная разработка);
  • версия Node в конфигурации CI/CD (GitHub Actions, GitLab CI, Jenkins);
  • версия Node в менеджерах процессов (PM2, systemd) и на serverless-платформе;
  • пакеты с нативным кодом (native addons) — список и статус поддержки целевой версии;
  • пакеты, чей engines ограничивает диапазон версий Node;
  • версия используемого SSR-фреймворка и его минимальные требования к Node;
  • драйверы БД, очередей и observability-агентов — совместимость с целевой веткой.

Регрессионные тесты перед переключением:

  • полный набор unit- и интеграционных тестов на целевой версии после npm ci и npm rebuild;
  • отдельный прогон обработчиков очередей: штатная остановка воркера, поведение retry-политики, потеря/сохранение задач в очереди;
  • отдельный прогон обработки вебхуков: идемпотентность при повторной доставке, проверка подписи, поведение при таймауте;
  • сравнение SSR-вывода (HTML) между старой и новой версией на одинаковых входных данных;
  • сравнение критичных API-эндпоинтов на теневом или canary-трафике по кодам ответа, задержке и содержимому;
  • проверка health-check эндпоинта на реальную готовность (БД, кэш, внешние зависимости), а не формальный 200 OK;
  • тест пути отката: возврат на предыдущую версию/образ без потери данных.

Ограничения, ошибки и риски

  • Путаница дат. Смотреть только на «Last updated» в таблице релизов и делать вывод о свежести версии — самая частая ошибка при аудите [1].
  • Тестирование только HTTP-слоя. Фоновые обработчики, очереди и cron-задачи почти всегда тестируются менее тщательно, чем API [20].
  • Забытые нативные зависимости. ABI-несовместимость нативных модулей проявляется не на этапе сборки, а в рантайме [10][14].
  • Рассинхронизация версий между окружениями. Локальная машина, CI и production используют разные версии Node из-за отсутствия зафиксированной версии в .nvmrc/engines.
  • Слепое обновление до самой новой версии. Node.js прямо предупреждает, что для продакшна должны использоваться только Active LTS или Maintenance LTS релизы [1].
  • Отсутствие плана отката. Переключение без заранее протестированного пути назад — это ставка, а не инженерное решение [19].

Как выбрать между готовым решением и разработкой

Для большинства случаев обновление версии Node — это плановая инженерная задача, которую штатная команда разработки в состоянии закрыть самостоятельно: инвентаризация, проверка зависимостей, тестирование и поэтапный деплой не требуют внешней разработки как таковой. Внешняя экспертиза становится оправданной, если:

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

Вывод

Node.js 20 достиг статуса EOL 30 апреля 2026 года, и это не аварийная ситуация, а плановая точка, которую бизнес должен был заложить в roadmap заранее [1][2]. Риск не в том, что приложение остановится само — окончание поддержки не означает немедленного прекращения работы, — а в том, что каждый день на EOL-версии увеличивает разрыв с экосистемой и накапливает неустранимые уязвимости. Практический путь: сначала найти все реальные точки использования Node.js — от Dockerfile до SSR-контейнера, — затем проверить зависимости и особенно нативные модули на ABI-совместимость, выбрать целевую LTS-ветку с учётом всего стека, отдельно протестировать фоновые обработчики и вебхуки, и только после сравнения на тестовом трафике переключать production поэтапно с готовым путём отката.

Источники

[1] nodejs.org — Node.js Releases — https://nodejs.org/en/about/previous-releases

[2] nodejs.org — End-Of-Life (EOL) — https://nodejs.org/en/about/eol

[3] cloudquery.io — AWS Lambda Node.js 20 EOL: Upgrade to Node.js 22 — https://www.cloudquery.io/blog/aws-lambda-nodejs-20-eol

[4] tuxcare.com — Node.js End-of-Life: Dates, Risks & What to Do Next — https://tuxcare.com/blog/node-eol/

[5] dev.to — Node.js End-of-Life Dates - Official EOL Schedule — https://dev.to/endoflifeai/nodejs-end-of-life-dates-official-eol-schedule-for-every-version-6do

[6] herodevs.com — Node.js v20 Is Reaching End of Life — https://www.herodevs.com/blog-posts/node-js-v20-is-reaching-end-of-life

[7] github.com — forcedotcom/cli, issue #3603 — https://github.com/forcedotcom/cli/issues/3603

[8] endoflife.ai — Node.js End of Life: Every Version's Dates — https://endoflife.ai/article-nodejs-eol

[9] nodejs.org — Node-API — https://nodejs.org/api/n-api.html

[10] medium.com — N-API Addons Break in 8 Sneaky Ways on Node Upgrades — https://medium.com/@Quaxel/n-api-addons-break-in-8-sneaky-ways-on-node-upgrades-b7419a289179

[11] versions.dev — Upgrade to Node.js 20 LTS — breaking changes & migration guide — https://versions.dev/modernize/node/upgrade-to-node-20

[12] versions.dev — Upgrade to Node.js 24 LTS — breaking changes & migration guide — https://versions.dev/modernize/node/upgrade-to-node-24

[13] pkgpulse.com — node-gyp vs prebuild vs napi-rs: Native Addons 2026 — https://www.pkgpulse.com/guides/node-gyp-vs-prebuild-vs-napi-rs-native-nodejs-addons-2026

[14] zylos.ai — Native Module ABI Compatibility in Containerized Node.js Agent Runtimes — https://zylos.ai/research/2026-06-17-native-module-abi-containerized-node-agent-runtimes/

[15] bdu.fstec.ru — Раздел угроз безопасности информации — https://bdu.fstec.ru/threat-section

[16] credos.ru — ФСТЭК БДУ – реестр угроз безопасности информации — https://www.credos.ru/articles-info/fstek-bdu-reestr-ugroz-bezopasnosti-informatsii/

[17] sgrc.cyberosnova.ru — Методика управления уязвимостями ФСТЭК: руководство 2026 — https://sgrc.cyberosnova.ru/blog/metodika-upravleniya-uyazvimostyami-fstek/

[18] dev.to — Node.js Graceful Shutdown in Production — https://dev.to/axiom_agent/nodejs-graceful-shutdown-in-production-sigterm-in-flight-draining-and-zero-downtime-deploys-2a7h

[19] dev.to — Zero-Downtime Deployments in Node.js: Blue-Green, Rolling, and Canary Explained — https://dev.to/axiom_agent/zero-downtime-deployments-in-nodejs-blue-green-rolling-and-canary-explained-192k

[20] dev.to — Node.js 26 vs Node.js 24 LTS: should you upgrade now? — https://dev.to/aarav_chandel_bf81a1120b1/nodejs-26-vs-nodejs-24-lts-should-you-upgrade-now-3l83

[21] 1xapi.com — Node.js Graceful Shutdown: Zero-Downtime Guide 2026 — https://1xapi.com/blog/nodejs-graceful-shutdown-zero-downtime-deployments-2026

Быстрые вопросы и ответы

Когда Node.js 20 получил статус EOL?

По официальному графику поддержки ветка Node.js 20 достигла конца жизни 24 марта 2026 года и больше не получает штатные исправления проекта.

Где проверять фактическую версию Node.js?

На production-серверах, в процесс-менеджерах, Dockerfile и базовых образах, CI/CD, средах сборки, serverless- и edge-конфигурациях.

Что чаще всего мешает обновлению?

Ограничения в поле engines, старые lock-файлы, нативные расширения и ABI, неподдерживаемые версии SSR-фреймворков и различия базовых образов.

Как обновить фоновые обработчики без потери заданий?

Проверяют подтверждение сообщений, повторные попытки и идемпотентность, останавливают приём новых задач старой версией и переключают воркеры контролируемо.

Как организовать безопасное переключение?

Новую версию поднимают параллельно, прогоняют критичные API и SSR на тестовом или зеркальном трафике, затем переключают долю запросов с заранее готовым откатом.

Нужна помощь по этой задаче?
На странице услуги «Инвентаризация зависимостей и безопасный план обновлений» указаны состав работ, результат и фиксированная цена.