Node.JS [ru] | Серверный JavaScript
Node.js, backend и AI-разработка: статьи, новости, вайбкодинг, автоматизация и работа с ИИ-агентами. Личный блог автора - @just_genych По вопросам рекламы или разработки: @g_abashkin РКН: https://vk.cc/cJPGOP
Показати більше📈 Аналітичний огляд Telegram-каналу Node.JS [ru] | Серверный JavaScript
Канал Node.JS [ru] | Серверный JavaScript (@we_use_js) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 11 186 підписників, посідаючи 11 029 місце в категорії Технології та додатки та 58 057 місце у регіоні Росія.
📊 Показники аудиторії та динаміка
З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 11 186 підписників.
За останніми даними від 09 липня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на -94, а за останні 24 години на -9, загальне охоплення залишається високим.
- Статус верифікації: Не верифікований
- Рівень залученості (ER): Середній показник залученості аудиторії становить 7.00%. Протягом перших 24 годин після публікації контент зазвичай збирає 4.69% реакцій від загальної кількості підписників.
- Охоплення публікацій: В середньому кожен допис отримує 783 переглядів. Протягом першої доби публікація в середньому набирає 525 переглядів.
- Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 2.
- Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як node.js, javascript, node, process.exit(1, модуль.
📝 Опис та контентна політика
Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
“Node.js, backend и AI-разработка: статьи, новости, вайбкодинг, автоматизация и работа с ИИ-агентами.
Личный блог автора - @just_genych
По вопросам рекламы или разработки: @g_abashkin
РКН: https://vk.cc/cJPGOP”
Завдяки високій частоті оновлень (останні дані отримано 10 липня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
Триває завантаження даних...
| Дата | Залучення підписників | Згадування | Канали | |
| 10 липня | 0 | |||
| 09 липня | 0 | |||
| 08 липня | 0 | |||
| 07 липня | 0 | |||
| 06 липня | +1 | |||
| 05 липня | +2 | |||
| 04 липня | 0 | |||
| 03 липня | +2 | |||
| 02 липня | +3 | |||
| 01 липня | 0 |
| 2 | Грейсфул шатдаун: как SIGTERM и postMessage ломают порядок сигналов
Каждый middle/senior разработчик Node.js сталкивался с грейсфул шатдауном, но редкий замечает скрытую ловушку — смешивание process.on('SIGTERM') и Worker.prototype.postMessage. Из-за разницы приоритетов событий и микрозадач теряются данные в production.
Проблема приоритетов событий
SIGTERM — системное событие с высоким приоритетом в цикле событий. postMessage — асинхронная операция, попадающая в очередь микрозадач. Если SIGTERM приходит до завершения отправки сообщения, оно обрабатывается уже после shutdown. Результат — потеря данных, которые должны были уйти в Worker.
Production-пример и диагностика
Рассмотрим типичный код:
process.on('SIGTERM', () => {
console.log('Shutdown');
worker.terminate();
});
worker.postMessage({ type: 'data', payload: result });
Здесь postMessage может быть прерван сигналом. Как диагностировать:
* Логируйте порядок событий с таймстемпами.
* Используйте process.on('SIGTERM', { once: true }) для однократного вызова.
* Проверяйте флаг isShuttingDown перед любым postMessage.
Практическое исправление
Решение — флаги состояния:
let isShuttingDown = false;
process.on('SIGTERM', () => { isShuttingDown = true; });
if (!isShuttingDown) worker.postMessage({ ... });
Для надёжности — SharedArrayBuffer для атомарной синхронизации между основным потоком и Worker, если требуется строгий контроль.
Типичная ошибка
Многие путают: проблема не в доступе к process из Worker threads — Worker его не имеет. Корень — порядок микрозадач в основном потоке, где postMessage может быть отложен после обработки SIGTERM.
Вывод: Используйте флаги состояния перед асинхронными операциями в обработчиках сигналов — это предотвращает потерю данных при грейсфул шатдауне. | 383 |
| 3 | Прошла половина лета
Выгореть ещё успеем. А пока лето — отправляемся загорать.
И не просто так, а со скидкой 5000 рублей по промокоду NETSIL от Яндекс Путешествий.
Забронировать
#реклама
travel.yandex.ru
О рекламодателе | 447 |
| 4 | Маск внезапно выкатил Grok 4.5 — первую версию, заточенную под код и агентов 😨
Обучали её в связке с Cursor, и по бенчмаркам она уже перепрыгивает GPT-5.5, заодно держится на уровне Opus 4.8. Terminal-Bench: у неё 83%, а у Opus 4.8 — 78,9%.
Прайсинг: $2/$6 за миллион токенов. «Opus-уровень, но шустрее, меньше жрет токенов и дешевле» — написал Маск в X. В Cursor она уже есть на всех тарифах. Завтра ждем ответочку от Альтмана 😊
👉 Node.JS [ru] | 474 |
| 5 | 🔍Тестовое собеседование на Frontend-разработчика с ex. TeamLead в Сбер
9 июля(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
📂 Даниил Дмитриев, старший разработчик в R-Vision, ex. TeamLead в Сбер, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Даниил будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Даниилу
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе. | 560 |
| 6 | Гео-аналитическая платформа вдвоём за 2,5 месяца: история spec-driven разработки
Автор поделился опытом старта проекта с чистого листа. Перед ним стояла амбициозная задача, не было легаси и была полная свобода выбора подхода. Он решил максимально довериться AI и больше не трогать код. Изначально были сомнения, что такой подход выдержит реальный масштаб, так как опыт подсказывал, что чем больше проект, тем быстрее AI путается в контексте и упирается в лимиты.
Через 2,5 месяца работы вдвоём удалось запустить гео-аналитическую платформу. Автор отмечает, что в до-AI эпоху такой проект строили бы годами. Этот опыт изменил его представление о разработке.
Читать далее | 520 |
| 7 | МТС Линк. Всё для коммуникации в команде
💻Платформа для общения, работы и обучения онлайн с поддержкой ИИ
Встречи, чаты и звонки в одном приложении
✅МТС Линк доступен в AppStore. Берите работу с собой и оставайтесь на связи с коллегами в любое время
Зарегистрироваться
#реклама 16+
mts-link.ru
О рекламодателе | 512 |
| 8 | Как один отказ бизнесу сэкономил компании 10 миллионов рублей
К концу проекта внедрения нового биллинга бизнес предложил перенести архивные продукты и исторические данные по ним. Архивные продукты использовались редко — для разбора спорных ситуаций с клиентами. Изначально было решено не избавляться от старого биллинга, а использовать его для чтения ретроданных. После оценки работ выяснилось, что типового механизма нет — нужно менять архитектуру, разрабатывать сценарии миграции, тестировать и поддерживать. Оценка составила около 10 миллионов рублей. Пересчет финансовой модели показал, что дополнительные инвестиции увеличивают срок окупаемости проекта на один год. Компания вкладывала бы деньги в функциональность без измеримой бизнес-ценности. Было принято решение отказать бизнесу и предложить оставить эти данные доступными для чтения в legacy биллинге.
Источник | 571 |
| 9 | Сидеть и работать в корпорации страшно, жизнь-то мимо проходит. Уходить строить бизнес страшно, а вдруг прогорит. Один из вариантов - разрабатывать свой пет-проект по вечерам. Многие успешные компании, например, Twitter, создавались именно так. Это не значит, что ваш проект обязательно заработает миллиарды, но заработать больше, чем в найме, и получить ценный опыт вполне реально.
Перед началом разработки появляется множество вопросов, например:
– Как выбрать идею для пет-проекта?
– Что нужно знать про маркетинг?
– Как запуститься и довести до первых продаж не имея бюджета на рекламу?
В телеграм-канале Твой пет проект, Михаил Табунов делится своим опытом с разработчиками и менеджерами.
Он рассказывает, где искать идею для нового проекта, что нужно знать о маркетинге, как запустить стартап и привлечь первых 10 клиентов, а также о многих других важных вещах.
Подписывайтесь на Твой пет проект получайте пользу от практиков рынка! | 563 |
| 10 | Онлайн-магистратура в ИТМО и МИФИ
Программы онлайн-магистратуры ИТМО и МИФИ в партнёрстве с Яндексом. Актуальные знания, практическое обучение и гибкий график. Учитесь, совмещая с работой. Доступна господдержка оплаты, отсрочка от армии
Перейти на сайт
#реклама 16+
practicum.yandex.ru
О рекламодателе | 584 |
| 11 | PROvoke на Analyst Days: как мы выступали в корсете и что из этого вышло
Привет, Хабр! В первой части я рассказывал, как мы с Татьяной Маркиной готовили доклад «Провоок» на Analyst Days — про споры, студию в Краснодаре, логистический ад и идею с кнутом и пряником. А сегодня — вторая часть: что произошло на сцене, какие роли мы играли, почему корсет так и не вышел в свет, и как один разговор в кулуарах перевернул моё понимание публичных выступлений. Подробности — во второй части статьи.
Источник: Анатомия парного доклада: как мы собирали «PROvoke» на Analyst Days. Часть 2 — выступление и фидбек | 629 |
| 12 | Выберите свой автомобиль Belgee на официальном сайте
Сочетание надёжности и комфорта. Широкий выбор комплектаций
Узнать больше
#реклама
belgee.ru
О рекламодателе | 595 |
| 13 | Buffer.write со str.length — тихая бомба под production.
Ты пишешь в буфер, передаёшь offset через str.length, и данные записываются в неверное место. Всё молча. Никаких ошибок. Просто битая информация.
В UTF-8 один символ может занимать от 1 до 4 байт. «Привет» — это 6 символов, но 12 байт. Если offset посчитан по длине строки, ты фактически говоришь Buffer: «запиши мне данные со смещением 6 байт». А нужно было с 12. Разница в два раза.
Я такое видел в production: кусок бинарного заголовка перезаписывался, файл читался как мусор. И никто не мог понять, почему.
Диагностика
— используй Buffer.byteLength(str, 'utf8') для вычисления реального размера в байтах;
— сравнивай str.length и Buffer.byteLength(str) — если различаются, в строке есть не-ASCII символы;
— проверяй логи, где размер буфера и смещение не сходятся.
Исправление
Простое решение:
const byteOffset = Buffer.byteLength(str, 'utf8');
buf.write(str, byteOffset);
Или вообще запиши с начала: buf.write(str, 0, 'utf8').
Типичная ошибка
— расчёт offset вручную через str.length * someCoefficient — это антипаттерн;
— молчаливое переполнение буфера без проверки остаточного места;
— путаница между символьным и байтовым смещением в одном бинарном сериализаторе.
Профилактика
— всегда считай байты через Buffer.byteLength();
— не вычисляй offset вручную для строк с Unicode;
— в TypeScript включай strict — он ловит часть таких косяков.
Вывод:
Silent data corruption — гадость редкая, но реальная. Проверь код: не используешь ли str.length как offset для Buffer.write? | 600 |
| 14 | Будьте в центре внимания — с Прайм-баннером
С новым медийным форматом Прайм-баннер вы можете не просто размещать рекламу на самых популярных сервисах Яндекса с высоким Brand Safety, а гибко управлять кампанией:
— Оптимизируйте стоимость размещения — формат доступен по аукционной модели без порога входа
— Настраивайте кросс-частоту и исключайте из показов неподходящие площадки
— Размещайтесь как на уже знакомых, так и на уникальных местах показа
— Выбирайте нужные среди более чем 600 таргетингов без наценок
— Оценивайте результаты с помощью исследований Brand Lift, Search Lift, Visit Lift и Target Lift
Узнайте больше о возможностях Прайм-баннера для вашего бренда.
Узнать больше
#реклама 16+
yandex.ru
О рекламодателе | 580 |
| 15 | Как я хакнул рынок труда: пишем свой ИИ-комбайн для автооткликов на HH.ru
Если вы хоть раз искали работу в IT за последний год, то знаете, что рынок беспощаден к новичкам. Нужно откликнуться на сотни вакансий, а в итоге получаешь отказы от роботов. Чтобы пробиться через фильтры HR, нужно под каждую вакансию писать уникальное сопроводительное письмо. В этой статье автор сделал полный разбор того, как написал собственного автономного ИИ-агента, который ищет вакансии, фильтрует мусор с помощью локальной нейросети, пишет персонализированные сопроводительные письма и отчитывается в Telegram, пока пользователь спокойно занимается своими делами. Скрипт задумывался бесплатным, автономным и не требующим настройки вокруг платных API.
Читать далее | 704 |
| 16 | Неявный deadlock в Node.js: AsyncLocalStorage + worker_threads + await в run()
Многие знают AsyncLocalStorage для проброса контекста, но скрещивание его с пулом worker_threads и await внутри колбэка run() создаёт неочевидный deadlock. Эта ошибка часто остаётся незамеченной до первого production-инцидента, когда пул потоков залипает при высокой нагрузке.
Как проявляется deadlock
Внутри run() вы помещаете ID запроса и вызываете await, пока воркер не закончит задачу. Если потоков в пуле ограниченное число (например, 2), а запросов много, каждый await блокирует run(), не освобождая поток из пула. Воркеры заняты, потоки ждут await — контекст AsyncLocalStorage не отпускается до полного завершения колбэка.
Пример problem:
const als = new AsyncLocalStorage();
async function processRequest(data) {
await als.run({ requestId: Date.now() }, async () => {
const worker = new Worker('./worker.js');
const result = await new Promise((resolve, reject) => {
worker.on('message', resolve);
worker.on('error', reject);
});
console.log(als.getStore().requestId);
});
}
Как обнаружить
- Залогируйте время выполнения воркеров: рост с увеличением числа запросов — тревожный сигнал.
- Используйте clinic.js или 0x: они покажут аномальные пики ожидания.
- Типичная ошибка: пул из 2 воркеров и 100 параллельных запросов — все зависнут через несколько секунд.
Практический совет
Не оставляйте await внутри run(). Вынесите ожидание наружу:
async function processRequest(data) {
const worker = new Worker('./worker.js');
const result = await new Promise(/*...*/);
als.run({ requestId: Date.now() }, () => {
console.log(als.getStore().requestId);
});
}
Либо передавайте контекст через worker.postMessage() — это проще и исключает deadlock.
Предупреждение
AsyncLocalStorage отлично работает на веб-серверах с краткими синхронными операциями, но await внутри run() с ограниченным пулом потоков — прямой путь к deadlock. Проверяйте такие места на этапе code review.
Вывод: Избегайте await внутри колбэка AsyncLocalStorage.run() при работе с пулом worker_threads — выносите асинхронное ожидание наружу или передавайте контекст через сообщения. | 632 |
| 17 | Диагностика и устранение неявной фрагментации кучи в Node.js
Long-lived HTTP серверы с разными по размеру payload часто страдают от "дырявой" кучи, хотя утечек памяти нет. Память фрагментируется из-за чередования маленьких и больших Buffer-ов, что ведет к росту RSS и частым GC паузам.
Как проявляется фрагментация
После обработки HTTP запросов создаются Buffer-ы разного размера: маленькие для заголовков, большие для тела. GC освобождает их неупорядоченно, оставляя пустоты между выделенными блоками. Со временем это увеличивает RSS на 20-40% без утечек. Симптомы: падение производительности через 12+' часов работы, частые stop-the-world паузы GC.
Диагностика в production
Первый шаг — трассировка с --trace-gc. Запустите: NODE_OPTIONS="--trace-gc" node app.js. В выводе ищите Mark-sweep паузы >50ms. Второй шаг — сравнение heapdump-ов через час и сутки работы в Chrome DevTools. Ищите фрагментированные объекты Buffer, разбросанные по куче. Третий шаг — проверьте флаги V8: node --v8-options | grep -i "heap.*frag".
Решение: Buffer Pool для однородности
Создайте пул Buffer-ов фиксированного сегмента, например 1024 байта. Это снижает разнообразие размеров и уменьшает фрагментацию. Пример:
class BufferPool {
constructor(size = 1024) {
this.pool = [];
this.size = size;
}
alloc(size) {
if (size > this.size) return Buffer.allocUnsafe(size);
if (this.pool.length) return this.pool.pop().slice(0, size);
return Buffer.allocUnsafe(this.size);
}
free(buf) { this.pool.push(buf); }
}
Практические советы и ошибки
- Для максимального снижения фрагментации используйте Buffer.allocUnsafeSlow вместо Buffer.allocUnsafe в пуле — он избегает shared memory pool.
- Настройте --max-old-space-size и --optimize-for-size для ограничения кучи.
- Типичная ошибка — использовать Buffer.allocUnsafe для всех случаев без разбора. Это увеличивает фрагментацию из-за случайных размеров.
- В Node 20+ можно изолировать тяжелые операции через --experimental-vm-modules в отдельных контекстах.
Вывод: Фрагментация кучи в long-lived серверах — реальная проблема, решаемая через Buffer Pool с фиксированным сегментом и контроль аллокаций, а не через поиск утечек. | 624 |
| 18 | Получи грант до 3,48 млн на обучение дизайну
Поступай на дизайн в Центральный университет с грантом.
Для учеников 10–11-х классов и СПО. Освой графический, UI/UX и продуктовый дизайн. Создавай визуальные концепты будущего.
На программе студенты получают фундаментальную базу, развивают прикладные навыки, приобретают опыт работы над реальными проектами, собирают портфолио и строят связи внутри дизайн-сообщества
Подать заявку
#реклама 16+
cu.ru
О рекламодателе | 491 |
| 19 | Скрытый убийца производительности: синхронный DNS в dns.lookup под нагрузкой
Высоконагруженный HTTP-клиент на Node.js внезапно теряет пропускную способность? Event loop залипает при большом количестве параллельных запросов? Чаще всего проблема не в HTTP, а в том, как система разрешает доменные имена.
В чем суть?
dns.lookup (используется http.request, https, axios по умолчанию) при вызове без флагов обращается к системному getaddrinfo через libuv. Этот вызов синхронный и блокирует event loop на время резолвинга. При 1000+ RPS latency одного разрешения (например, 50 мс) превращается в 50 000 мс общего блокирования цикла.
Как диагностировать?
1. Подключить dns.promises и выполнить dns.promises.lookup при нагрузке. Если event loop задерживает микротаски, виновник найден.
2. Использовать process.hrtime.bigint() до и после dns.lookup - разница > 10 мс системного времени указывает на проблему.
3. clinic doctor - на графике async latency видны ступеньки, совпадающие с пиками DNS-запросов.
Как устранить?
Для http(s) агентов - замена на асинхронный DNS:
const { createConnection } = require('net');
const dns = require('dns/promises');
const agent = new http.Agent({
createConnection: async (options, cb) => {
const { address } = await dns.lookup(options.hostname);
const socket = createConnection({ ...options, host: address });
cb(null, socket);
},
});
Типичная ошибка: использование только maxSockets или scheduling: 'lifo' снижает частоту новых соединений, но не решает первопричину при множестве уникальных хостов. Проще - библиотеки dns-cache или cacheable-lookup.
Вывод: блокировка из-за dns.lookup - классическая проблема одного потока Node.js на стыке системных вызовов, решается заменой на асинхронное разрешение через dns.promises или кастомный агент. | 671 |
| 20 | Диагностика и устранение гонок данных при конкурентном доступе к node:sqlite из worker_threads через in-memory WAL-режим
В production сценариях с worker_threads и in-memory SQLite в WAL режиме разработчики часто забывают синхронизировать доступ. Итог — SQLITE_BUSY, рассинхрон данных и дубли в уникальных полях.
Проблема: гонка без синхронизации
Несколько воркеров читают и пишут в одну in-memory базу без внешней координации. WAL помогает с параллельным чтением, но не спасает от гонок записи. Типичные проявления: ошибки SQLITE_BUSY, частичные обновления и потеря данных.
Решение: один писатель с явными блокировками
Выделите один воркер для критических записей (например, инкременты). Координируйте через SharedArrayBuffer и Atomics — это дешевле мьютексов. Воркеры-читатели используют отдельные соединения в WAL.
Production-oriented пример с BEGIN IMMEDIATE
Начиная с Node.js 23 используйте DatabaseSync. Обязательно PRAGMA journal_mode=WAL; и PRAGMA synchronous=NORMAL;:
import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:', { readwrite: true, create: true });
db.exec('PRAGMA journal_mode=WAL;');
db.exec('PRAGMA synchronous=NORMAL;');
function safeUpdate(sql) {
db.exec('BEGIN IMMEDIATE;');
try {
db.exec(sql);
db.exec('COMMIT;');
} catch {
db.exec('ROLLBACK;');
throw new Error('Write failed');
}
}
BEGIN IMMEDIATE блокирует запись сразу, избегая гонок. Без него два воркера могут начать транзакции одновременно — ловите SQLITE_BUSY.
Предупреждение: in-memory WAL не для продакшена
In-memory база теряет данные при краше. Для реальных проектов используйте файловую базу с WAL — это гарантирует персистентность.
Вывод: гонки данных в SQLite лечатся одним писателем и явными блокировками через BEGIN IMMEDIATE, давая скорость WAL без потери консистентности. | 675 |
