Node.js
Node.js — серверне середовище для JavaScript, що виконує весь ваш код в одному потоці й передає кожне очікування операційній системі або невеликому пулу потоків. Саме через цей задум один процес тримає десять тисяч простійних з’єднань — і саме через нього одна повільна функція затримує всі запити одночасно. Сторінка починається з сімнадцяти дій Node-сервера й того, який потік платить за кожну; далі — цикл подій і пул, релізи й підтримка (з Node 27 — один мажорний реліз на рік), що тепер вбудовано, масштабування й коректна зупинка, п’ять задокументованих кейсів і те, де все це вироджується.
- Поточна версія
- 26 · LTS з 28 жовт. 2026
- Модель
- Один потік для вашого коду
- Підтримка
- 30 місяців LTS; з 27 — мажор на рік
Де виконується кожна робота — сімнадцять дій Node-сервера
Сервер на Java чи Go дає запиту, що чекає, власний потік, тож повільний запит гальмує здебільшого сам себе. Node дає вашому коду рівно один потік. Усі запити процесу по черзі працюють на ньому — ця черговість і є event loopодин потік, що виконує все по черзіЦикл в одному потоці, що бере з черги готову роботу — відповідь, яка прийшла, таймер, що спрацював, — і виконує її колбек, по одному за раз. Він дає одному потоку тримати тисячі очікувань одночасно й зупиняється для всіх, поки виконується будь-який один колбек.Докладніше в статті →Усі терміни, цикл подій, — а все, що не вміє чекати без потоку, відправляється деінде. Тож корисне питання до будь-якого рядка серверного коду — не «чи він швидкий?», а «який потік за нього платить і хто чекає, поки він виконується?». Ось сімнадцять дій Node-сервера з відповіддю для кожної. Наступні розділи посилаються на рядки за номерами.
| # | Що робить сервер | Де це виконується | Хто чекає, поки це триває |
|---|---|---|---|
| 1 | Власний код обробника між двома await | Потік циклу | Кожен інший запит у процесі |
| 2 | JSON.parse() тіла запиту на 20 МБ | Потік циклу | Кожен запит — десятки мілісекунд |
| 3 | Регулярний вираз над даними від користувача | Потік циклу | Кожен запит — секундами, якщо шаблон робить відкати |
| 4 | Сортування, фільтрація чи підсумовування великого масиву | Потік циклу | Кожен запит |
| 5 | Рендеринг HTML на сервері — шаблон, React | Потік циклу | Кожен запит |
| 6 | Будь-який виклик …Sync — readFileSync, pbkdf2Sync, gzipSync | Потік циклу | Кожен запит — на весь час читання з диска чи обчислення |
| 7 | console.log у файл або в термінал на Linux | Потік циклу — такий запис синхронний | Кожен запит; запис у pipe — асинхронний |
| 8 | Запит до бази даних мережею — PostgreSQL, MySQL, Redis | Ядро ОС — жоден потік не чекає | Ніхто; розбір відповіді — знову рядок 1 |
| 9 | Утримання десяти тисяч простійних з’єднань чи WebSocket | Ядро ОС — жоден потік не чекає | Ніхто; кожне коштує пам’яті, а не потоку |
| 10 | Таймер — setTimeout, setInterval | Потік циклу, коли спрацьовує | Ніхто — але він спрацьовує пізно, поки йдуть рядки 1–7 |
| 11 | Кожен асинхронний виклик fs — readFile, writeFile, stat | Пул потоків — чотири потоки | Інші рядки пулу |
| 12 | dns.lookup() — його викликають http, fetch і більшість драйверів баз даних для кожного імені хоста | Пул потоків — чотири потоки | Інші рядки пулу; повільний DNS-сервер тримає потік на кожен запит імені |
| 13 | crypto.pbkdf2, scrypt, randomBytes, generateKeyPair | Пул потоків — чотири потоки | Інші рядки пулу |
| 14 | Асинхронний zlib — gzip і Brotli | Пул потоків — чотири потоки | Інші рядки пулу |
| 15 | Асинхронна робота нативного доповнення — гешування пакетом bcrypt | Пул потоків, зазвичай | Інші рядки пулу |
| 16 | Воркер worker_threads | Власний потік із власним циклом подій | Ніхто в основному циклі; дані копіюються туди й назад |
| 17 | Дочірній процес або споживач, що бере задачі з черги | Інший процес | Ніхто в цьому процесі |
Цикл, що не має права чекати, і пул із чотирьох
Традиційний сервер дає кожному з’єднанню потік, і цей потік стоїть заблокований, поки відповідає база даних. Node взагалі ніколи не блокується на з’єднанні. Він просить операційну систему стежити за всіма сокетами одразу — epoll у Linux, kqueue у macOS, IOCP у Windows — і повідомляти, які з них готові. Тож десять тисяч простійних з’єднань коштують десять тисяч маленьких об’єктів у пам’яті, а не десять тисяч потоків. Коли сокет готовий, libuv — бібліотека на C під Node — ставить його колбек у чергу, і потік циклу його виконує.
Цикл іде по колу фазами: спершу таймери, чий час настав, потім колбеки завершеного вводу-виводу, потім колбеки setImmediate, потім закриті з’єднання — і знову по колу. Між будь-якими двома колбеками він вичерпує чергу виконаних промісів. Правила порядку промісів і таймерів — тема сторінки про JavaScript; для сервера важить один наслідок. Колбек ніколи не переривається. Поки він виконується, цикл не рухається, тож жоден інший запит не розбирається, жодна відповідь не надсилається, жоден таймер не спрацьовує. Тому та сама повільна функція в Java — прикрість, а в Node — аварія.
Вимірювання, що називає цю проблему, — затримка циклу подій: наскільки пізніше, ніж мав, цикл повертається до роботи. perf_hooks.monitorEventLoopDelay(), доступний з Node 11, записує її як гістограму; експортуйте 99-й процентиль як метрику поруч із латентністю. Друге число — завантаженість циклу з performance.eventLoopUtilization() — каже, яку частку часу цикл узагалі був зайнятий. Коли затримка росте, причина — синхронний код у вашому ж процесі (рядки 1–7), і жодне налаштування бази даних її не зрушить. Функцію знаходить профіль процесора: node --cpu-prof записує файл, який Chrome DevTools відкриває як флейм-граф.
Пул із чотирьох і пастка DNS
Для деяких операцій операційна система не має інтерфейсу «скажи, коли буде готово»: читання файлу, пошук імені хоста через системний резолвер, гешування пароля, стиснення відповіді. libuv виконує їх на пулі потоків — рядки 11–15, — і в пулі типово чотири потоки. Документація прямо називає наслідок: якщо будь-яка з цих операцій триває довго, «інші (на перший погляд не пов’язані) APIApplication Programming Interface — контракт між програмамиПравила, за якими одна програма звертається до іншої: які запити можна надіслати, у якому вигляді й що прийде у відповідь. Для того, хто звертається, це контракт — усе, що за ним, лишається чорною скринькою, і саме тому другий бік можна переписати, не зламавши вас.Докладніше в статті →Усі терміни, що працюють у пулі потоків libuv, деградуватимуть». Чотири одночасні входи з гешуванням паролів заповнюють пул, і запит, що хотів лише прочитати маленький файл, чекає за ними.
Пастка, яку більшість команд знаходить на власному досвіді, — рядок 12. Пошук імені хоста через dns.lookup() з боку JavaScript виглядає асинхронним, але документація каже, що він «реалізований як синхронний виклик getaddrinfo(3), що виконується в пулі потоків libuv», — а модуль http, fetch і більшість драйверів баз даних викликають його для кожного імені хоста, до якого під’єднуються. DNS-сервер, що відповідає п’ять секунд, тримає потік пулу п’ять секунд на кожен такий пошук. Чотири таких пошуки — і кожне читання файлу в процесі стоїть за ними в черзі, хоча диск простоює, а процесор теж.
Є три виправлення, у порядку того, як часто вони правильні. Перевикористовуйте з’єднання, щоб ім’я хоста розв’язувалося один раз, а не на кожен запит, — це робить агент із keep-alive. Винесіть важке гешування й стиснення зі спільного пулу: у воркер-потік, в окремий сервіс або в бібліотеку з власними потоками. І якщо пул справді має бути більшим, задайте UV_THREADPOOL_SIZE у середовищі до старту Node; максимум — 1024. Задавати його зсередини коду «не гарантовано спрацює», попереджає документація, бо пул створюється раніше, ніж виконується ваш перший рядок.
| Що ви бачите | Що це зазвичай означає | Куди дивитися |
|---|---|---|
| Латентність росте для всіх ендпоінтів одразу, одне ядро на 100% | Щось тримає потік циклу (рядки 1–7) | Затримка циклу, потім профіль процесора |
| Читання файлів і вихідні виклики гальмують лише під час сплеску входів | Пул заповнено (рядки 11–15) | Скільки гешування й стиснення йде одночасно |
| Вихідні виклики повільні, а віддалений сервіс звітує, що він швидкий | Розв’язання імен у пулі (рядок 12) | Латентність DNS; чи перевикористовуються з’єднання |
| Пам’ять годинами росте, доки контейнер не вб’ють | Витік — зазвичай кеш рівня модуля, слухач чи таймер, які ніхто не прибрав | Два знімки купи з інтервалом у годину, порівняні між собою |
| Процес завершується одразу після рядка в лозі про необроблене відхилення | Проміс завершився помилкою, і ніхто його не чекав, — фатально з Node 15 | Трасування в цьому рядку логу; пропущений await чи .catch() |
Релізи: Current, LTS і зміна, що починається цього місяця
До версії 26 Node випускав два мажорні релізи на рік. Парні номери виходили у квітні, непарні — у жовтні. Кожна парна лінія пів року була «Current», а в жовтні ставала лінією LTSLong-Term Support — реліз, що роками отримує патчіЛінія релізів, що й далі отримує виправлення безпеки та критичних багів упродовж оголошеного строку після виходу новіших версій, але без нових можливостей. Вона дає команді оновлюватися у власному темпі — до кінцевої дати в таблиці підтримки, після якої наступна вразливість не матиме виправлення взагалі.Усі терміни — довгострокової підтримки — з 12 місяцями активних виправлень і ще 18 місяцями супроводу: разом 30 місяців. Непарні лінії жили близько восьми місяців і ніколи не отримували LTS. Правило для продакшену випливало саме: запускати парну лінію LTS і оновлюватися до дати кінця її підтримки. Таблиця перелічує, що кожна недавня лінія додала такого, що ви зустрінете в коді, і як довго вона отримує патчі.
| Версія | Випущено | Що ви зустрінете в коді | Підтримка до |
|---|---|---|---|
| 18 | квіт. 2022 | Глобальний fetch без прапорця, експериментальний вбудований тест-ранер | Завершено 30 квіт. 2025 |
| 20 | квіт. 2023 | Стабільний тест-ранер, модель дозволів як експеримент, --env-file | Завершено 30 квіт. 2026 |
| 22 | квіт. 2024 | require() ES-модулів, клієнт WebSocket, стабільний --watch, node --run, node:sqlite, TypeScript-файли запускаються напряму | 30 квіт. 2027 |
| 24 | трав. 2025 | npm 11, URLPattern як глобальний об’єкт, оголошення using, стабільне видалення типів | 30 квіт. 2028 |
| 26 | трав. 2026 | Temporal увімкнено за замовчуванням, Undici 8, --experimental-transform-types прибрано | 30 квіт. 2029 |
| 27 | Alpha з 28 жовт. 2026; 27.0.0 у квіт. 2027 | Перша лінія за новим розкладом; тайм-аут keep-alive 65 с за замовчуванням | 30 квіт. 2030 |
Що тепер вбудовано: модулі, TypeScript і менше пакетів
У Node дві системи модулів, і більшість проєктів досі зустрічає обидві. CommonJS — require() і module.exports — початкова, вона розв’язується під час виконання коду. ES-модулі — import і export — стандарт мови. Роками межа між ними була стіною: файл CommonJS не міг зробити require() ES-модуля, тож одна залежність, що перейшла лише на ESM, змушувала своїх користувачів мігрувати. З Node 22.12 і 20.19 це працює без прапорця, а з 25.4 — стабільно. Лишився один виняток: модуль із await верхнього рівня так завантажити не можна, і виклик падає з ERR_REQUIRE_ASYNC_MODULE. Новий код має бути на ES-модулях, з "type": "module" у package.json.
Node тепер також запускає TypeScriptJavaScript із перевіркою типівJavaScript плюс опис того, що саме функція приймає й повертає, — і цей опис перевіряється в редакторі ще до запуску. У браузер він не потрапляє: перед складанням його компілюють назад у звичайний JavaScript, тож типи — це інструмент розробки, і не більше.Докладніше в статті →Усі терміни-файли напряму: за замовчуванням з 22.18, стабільно з 24.12. Варто точно знати, що це означає, бо назва обіцяє більше, ніж є. Node видаляє анотації типів — замінює їх пробілами — і виконує те, що лишилося. Перевірки типів немає зовсім, тож код із помилкою типів однаково запускається. tsconfig.json ігнорується, тож псевдоніми шляхів не розв’язуються. Підтримується лише синтаксис, який можна стерти: enum чи властивість-параметр конструктора потребують згенерованого коду й відхиляються. І TypeScript-файли всередині node_modules Node обробляти відмовляється, тож пакети далі публікують JavaScript. Лишіть tsc --noEmit у збірці: Node замінює крок виводу компілятора, а не його перевірку.
| Пакет, який може вже не знадобитися | Що вбудовано натомість | З версії |
|---|---|---|
node-fetch, axios для простих викликів | Глобальний fetch | 18; стабільний у 21 |
jest, mocha для власних тестів бібліотеки | node:test і node --test | Стабільний у 20 |
nodemon | node --watch | Стабільний у 22 |
dotenv | node --env-file=.env | 20.6; стабільний у 24.10 |
ts-node, tsx для коду без enum | Видалення типів | 22.18; стабільне в 24.12 |
ws як клієнт | Глобальний WebSocket | 22 |
npm run лише щоб запустити скрипт | node --run | 22 |
better-sqlite3 | node:sqlite | 22.5; ще не стабільний |
Саме на етапі встановлення живе справжній ризик ланцюга постачання в Node, і це інший ризик, ніж той, що описує сторінка про JavaScript. Та сторінка — про дерево залежностей, тобто про те, що ви постачаєте користувачам. Ця — про те, що виконується на вашій машині. npm install запускає скрипти preinstall, install і postinstall кожного пакета з правами вашого користувача: на ноутбуці, де є ключі SSH, на сервері збірки, що тримає облікові дані хмари. Три заходи закривають більшу частину ризику. Встановлюйте через npm ci із закоміченого lockfileточні версії кожної залежностіФайл, який менеджер пакетів пише поряд зі списком залежностей і в якому записано точну версію кожного встановленого пакета — зокрема тих, що підтягнули ваші залежності. Закомічений у репозиторій, він робить кожне встановлення однаковим; без нього дві збірки того самого коміту можуть виконувати різний код.Усі терміни. Запускайте це з --ignore-scripts у конвеєрі й дозволяйте скрипти лише кільком пакетам, що компілюють нативний код. Або візьміть pnpm, який з версії 10, із січня 2025 року, не запускає скриптів залежностей, якщо їх не перелічено.
Масштабування, падіння і коректна зупинка
Один процес Node використовує для вашого коду одне ядро, тож шістнадцятиядерна машина з одним процесом використовує одну шістнадцяту того, за що ви заплатили. Виходів три, і вони не взаємозамінні: кожен пасує іншій формі задачі.
| Підхід | Що це | Коли брати |
|---|---|---|
| Більше процесів | N копій за балансувальником навантаження — на практиці один процес на контейнер, а репліки додає оркестратор. | Майже завжди. Це типова відповідь для HTTP-сервісу без стану. |
worker_threads (рядок 16) | Справжні потоки в одному процесі, кожен із власним циклом подій і без спільних змінних. | Одна важка операція всередині сервісу, що загалом чекає, — PDF, зображення, великий розбір. |
| Черга (рядок 17) | Покласти задачу до брокера й дати окремому процесу-споживачу її виконати. | Робота, що може завершитися після відповіді: звіти, листи, медіа, імпорти. |
Що б ви не обрали, обмеження однакове: процеси нічого не ділять, тож кеш у пам’яті, лічильник обмеження частоти чи сесія в змінній рівня модуля хибні тієї миті, коли з’явився другий процес. Їхнє місце — у Redis чи базі даних. Воркер-потік теж не дешевий потік: він запускає власну копію рушія, коштує мегабайти й десятки мілісекунд на старт і отримує дані копією. Тримайте невеликий пул живих воркерів і надсилайте їм задачі, а не запускайте по одному на запит.
Коректна зупинка і 502, який ніхто не може відтворити
Оркестратор зупиняє контейнер, надсилаючи SIGTERM, а після пільгового періоду — у Kubernetes типово тридцять секунд — убиває його. Процес, що ігнорує сигнал, на кожному деплої втрачає всі запити в польоті. Обробіть його: викличте server.close(), що перестає приймати з’єднання, а з Node 19 ще й закриває простійні; дайте запитам у польоті завершитися; закрийте пул з’єднань із базою; вийдіть із запасом до кінця пільгового періоду.
Другий збій не потребує жодного деплою. Балансувальник навантаження тримає простійні з’єднання з вашим процесом відкритими, щоб перевикористати їх для наступного запиту. Application Load Balancer в AWS типово тримає їх 60 секунд. Node закриває простійне з’єднання після свого keepAliveTimeout — типово 5 секунд, плюс секунда запасу з 24.6 і 22.19. Тож Node завжди закриває першим. Здебільшого це нешкідливо. Але коли балансувальник надсилає запит у з’єднання саме тієї миті, коли Node його закриває, запит натрапляє на сокет, що закривається, і клієнт отримує 502 Bad Gateway. AWS документує саме це й радить, щоб тайм-аут простою застосунку був довшим за тайм-аут балансувальника.
Дорогим його робить симптом: кілька 502 на багато тисяч запитів, жодної помилки в лозі застосунку й нічого на тихому тестовому середовищі, бо гонці потрібен справжній трафік, щоб влучити в точну мить. Виправлення — один рядок: server.keepAliveTimeout = 65_000, довше за 60 секунд балансувальника, — і сам Node з версії 27 дотримується того самого погляду: 65 секунд стають значенням за замовчуванням. До того кожному сервісу за балансувальником потрібен цей рядок.
П’ять кейсів і те, чого в кожному бракувало
Кожен кейс задокументували ті, з ким він стався: інженерні блоги, власний журнал змін і записи релізів проєкту, бюлетень безпеки, оголошення реєстру. Разом вони покривають ставку, яку робить Node, його врядування, цикл, залежність на циклі й етап встановлення.
| Кейс | Що сталося | Чого бракувало |
|---|---|---|
| PayPal, 2013 | Та сама сторінка на Java і на Node: удвічі більше запитів за секунду на одному ядрі проти п’яти | Нічого — але результат стосується сторінок, що чекають, і допис так і каже |
| io.js, 2014–2015 | Контриб’ютори форкнули Node через врядування й завмерлий ритм релізів; проєкти злилися в Node 4 | Відкрите врядування й передбачуваний розклад |
| Netflix, лист. 2014 | Латентність росла на 10 мс щогодини до перезапусків — через дублікати обробників маршрутів | Профіль процесора для циклу |
| path-to-regexp, вер. 2024 | Один підготовлений URL тримав цикл будь-якого застосунку на Express 4 із маршрутом /:a-:b | Шаблон без відкатів і обмеження довжини URL |
| Shai-Hulud, вер. і лист. 2025 | Хробак поширювався через скрипти встановлення npm, крав токени й публікував сам себе | Вимкнені за замовчуванням скрипти встановлення, короткоживучі токени публікації |
Перший кейс — сама ставка, виміряна чесно. У 2013 році PayPal переписав на Node сторінку огляду рахунку, одну з найнавантаженіших на сайті, а команда паралельно будувала ту саму сторінку на Java, на власному фреймворку на основі Spring, як запасний варіант. Обидві пройшли ті самі функціональні тести. У листопаді 2013 року Джефф Гаррелл опублікував цифри: версію на Node збудували майже вдвічі швидше меншою командою, і вона обслуговувала вдвічі більше запитів за секунду — «з одним ядром для застосунку на node.js проти п’яти ядер у Java», — з середнім часом відповіді на 35% меншим, приблизно на 200 мс. Деталь, що це пояснює, — у тому самому дописі: кожен із трьох маршрутів сторінки робив від двох до п’яти запитів до API і зшивав відповіді. Це рядки 8 і 9: сторінка, що все життя чекає. Допис закінчується власним застереженням — «у вас може бути інакше», — і воно слушне. Те саме переписування сторінки, що обчислює, показало б протилежне.
Третій кейс — рядок 1, схований усередині фреймворку. У листопаді 2014 року Юнонг Сяо описав у Netflix Tech Blog Node-сервіс, латентність якого починалася з 1 мс і росла на 10 мс щогодини, сягаючи близько 60 мс, перш ніж інстанси перезапускали. Разом із нею ріс і процесор. Власні обробники команди стабільно показували 1 мс, а купа трималася біля 1,2 ГБ, тож винні не були ні їхній код, ні витік пам’яті у звичному сенсі. Флейм-граф процесора показав дуже високі стеки всередині маршрутизатора Express. Express тримав усі обробники маршрутів в одному масиві й проходив його на кожен запит. Завдання в коді Netflix десять разів на годину оновлювало маршрути із зовнішнього джерела — і щоразу ще й додавало той самий обробник статичних файлів, попереду маршрутів API. Кожен дублікат коштував близько 1 мс на кожному запиті: десять за годину — 10 мс за годину. Ніщо не падало; цикл просто щогодини робив на запит більше роботи. Поступові перезапуски це ховали. Профіль знайшов.
П’ятий кейс — етап встановлення. 14 вересня 2025 року GitHub повідомили про Shai-Hulud — хробака, що сам себе відтворював: він потрапив у npm через зламані облікові записи мейнтейнерів і вставляв у їхні пакети скрипти post-install. Коли розробник чи сервер збірки встановлював заражену версію, скрипт шукав на машині секрети — серед них токени npm і облікові дані хмари — і з кожним знайденим токеном npm публікував заражені версії інших пакетів того самого мейнтейнера. GitHub видалив понад 500 пакетів. 22 вересня він оголосив зміну моделі: локальна публікація з двофакторною автентифікацією, гранулярні токени, що живуть сім днів, довірена публікація із систем збірки й відмова від класичних токенів. Друга хвиля в листопаді 2025 року перейшла на preinstall — він виконується ще до повного встановлення пакета, — зачепила близько 700 пакетів і лишила понад 25 000 репозиторіїв GitHub з украденими секретами. Кожне зараження починалося однаково: скрипт встановлення, що працює з правами того, хто набрав npm install.
Де він вироджується
Модель Node безжальна в один бік і щедра в інший. Чекання майже безкоштовне, тож сервіс, що лише чекає, на одному процесі масштабується далі, ніж більшість середовищ на двадцяти потоках. Обчислення ділять усі, тож один необережний рядок оподатковує всіх користувачів одразу. Майже кожен збій — це один із сімнадцяти рядків, поставлений не в той потік:
- Розбір, сортування, рендеринг чи гешування в потоці циклу гальмує кожен паралельний запит (рядки 1–6).
- Регулярний вираз, написаний вручну й застосований до вводу користувача без обмеження довжини (рядок 3).
- Гешування паролів, стиснення й DNS, що б’ються за чотири потоки пулу (рядки 11–15).
- Жодної метрики затримки циклу, тож єдине число, що пояснює сповільнення, ніколи не потрапляє на дашборд.
- Стан у змінній рівня модуля, що тихо розходиться тієї миті, коли з’являється другий процес.
- Глобальний обробник, що ковтає помилки й лишає процес працювати в невідомому стані.
- Жодного обробника
SIGTERM, тож кожен деплой обриває запити в польоті. - Тайм-аут keep-alive за замовчуванням за балансувальником, що виявляється рідкісними 502, які ніхто не може відтворити.
- Скрипти встановлення, що виконуються на серверах збірки, які тримають токени публікації й облікові дані хмари.
- Лінія після дати кінця підтримки — сьогодні це все, що старше за 22.
Чесна межа — сам єдиний потік. Сервіс, чиї запити обчислюють, а не чекають, — обробка зображень, аналітика, важкі перетворення, — бореться з моделлю на кожному кроці. Воркер-потоки й черги виносять роботу назовні, але тоді більша частина сервісу написана довкола того, щоб забрати роботу від Node, і середовище зі справжніми потоками чи компільована мова були б простішим вибором. Справедливе й протилежне: причини, з яких команди йдуть із Node, часто виявляються рядками 1–7, які профіль знайшов би за один день.
Практична перевірка займає п’ять хвилин. Запустіть node -v у продакшн-образі й знайдіть рядок у таблиці релізів. Перевірте, що затримка циклу подій експортується, і подивіться на її 99-й процентиль у пік. Порівняйте keepAliveTimeout з тайм-аутом простою балансувальника. І подивіться, як конвеєр встановлює залежності: npm ci, зі скриптами вимкненими, з lockfile.
Коли це застосовувати
Застосовуйте, коли
- API та шлюзи, чия робота — викликати інші системи й формувати їхні відповіді.
- Реальний час — WebSocketпостійний двосторонній звʼязокЗʼєднання, що лишається відкритим в обидва боки: на відміну від HTTP, сервер може надіслати повідомлення сам, не чекаючи запиту. На ньому тримаються чати й живі стрічки — і більшість того, що виглядає як сторінка, що оновлюється сама.Усі терміни, потоки, довгі з’єднання, — де тримати багато простійних сокетів дешево.
- Команди, які вже пишуть фронтенд на TypeScript: вони отримують спільні типи й один інструментарій з обох боків.
- Застосунки з рендерингом JavaScript на сервері, де фреймворку середовище Node потрібне так чи інакше.
Уникайте, коли
- Сервіси, чиї запити обчислюють, а не чекають, — кодування, аналітика, важкі перетворення.
- Усе, що потребує спільного змінюваного стану в процесі: він не переживає появи другого процесу.
- Середовища збірки, де не можна вимкнути скрипти встановлення чи тримати токени публікації короткоживучими.
- Лінія після дати кінця підтримки — сьогодні все, що старше за 22.
Джерела й метод
На чому стоїть ця стаття
- 19 джерел
- 3 задокументовані збої
- Перевірено 13 жовтня 2026 р.
Практики й походження термінів
який потік платить за кожну операцію, і графік релізів- ДокументаціяNode.js — Command-line API (UV_THREADPOOL_SIZE) (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — DNS: Implementation considerations (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — Process: A note on process I/O (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — HTTP (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — Modules: TypeScript (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — Modules: CommonJS modules (відкривається в новій вкладці)nodejs.org
- ДокументаціяNode.js — Permissions (відкривається в новій вкладці)nodejs.org
- Документаціяlibuv — Thread pool work scheduling (відкривається в новій вкладці)libuv
- ДокументаціяEdit attributes for your Application Load Balancer (відкривається в новій вкладці)AWS Elastic Load Balancing
- Документаціяnodejs/Release — Node.js Release Working Group (відкривається в новій вкладці)GitHub
- СтаттяEvolving the Node.js Release Schedule (відкривається в новій вкладці)Node.js Blog · 10.03.2026
Збої, на яких вчиться стаття
Netflix, path-to-regexp і Shai-Hulud у «П’ять кейсів»- ПостмортемYunong Xiao — Node.js in Flames (відкривається в новій вкладці)Netflix Technology Blog · 19.11.2014
- Документаціяpath-to-regexp outputs backtracking regular expressions (CVE-2024-45296) (відкривається в новій вкладці)GitHub Advisory Database · 09.09.2024
- ПостмортемXavier René-Corail — Our plan for a more secure npm supply chain (відкривається в новій вкладці)The GitHub Blog · 22.09.2025
- СтаттяSha1-Hulud 2.0 Supply Chain Attack: 25K+ Repos Exposed (відкривається в новій вкладці)Wiz · 11.2025
- Документаціяpnpm 10 — release notes (відкривається в новій вкладці)GitHub · pnpm · 07.01.2025
Дослідження з Claude. Пошук і звірку першоджерел зроблено з Claude (Anthropic). Відбір, текст і перевірку фактів — редакція Anatomy of IT Product.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.